Object.getOwnPropertyNames vs Object.keys

В чем разница между Object.getOwnPropertyNames и Object.keys в javascript? Также будут оценены некоторые примеры.

Ответ 1

Есть небольшая разница. Object.getOwnPropertyNames(a) возвращает все собственные свойства объекта a. Object.keys(a) возвращает все перечислимые собственные свойства. Это означает, что если вы определяете свои свойства объекта, не делая некоторые из них enumerable: false, эти два метода дадут вам тот же результат.

Легко проверить:

var a = {};
Object.defineProperties(a, {
    one: {enumerable: true, value: 'one'},
    two: {enumerable: false, value: 'two'},
});
Object.keys(a); // ["one"]
Object.getOwnPropertyNames(a); // ["one", "two"]

Если вы определяете свойство без указания дескриптора атрибутов свойств (это означает, что вы не используете Object.defineProperties), например:

a.test = 21;

то такое свойство становится перечислимым автоматически, и оба метода создают один и тот же массив.

Ответ 2

Другое отличие состоит в том, что в случае с методом array Object.getOwnPropertyNames будет возвращено дополнительное свойство length.

var x = ["a", "b", "c", "d"];
Object.keys(x);  //[ '0', '1', '2', '3' ]
Object.getOwnPropertyNames(x);  //[ '0', '1', '2', '3', 'length' ]

Ответ 3

Буквальная нотация против конструктора при создании объекта. Это то, что меня достало.

const cat1 = {
    eat() {},
    sleep() {},
    talk() {}
};

// here the methods will be part of the Cat Prototype
class Cat {
    eat() {}
    sleep() {}
    talk() {}
}

const cat2 = new Cat()

Object.keys(cat1) // ["eat", "sleep", "talk"]
Object.keys(Object.getPrototypeOf(cat2)) // []

Object.getOwnPropertyNames(cat1) // ["eat", "sleep", "talk"]
Object.getOwnPropertyNames(Object.getPrototypeOf(cat2)) // ["eat", "sleep", "talk"]

cat1 // {eat: function, sleep: function, talk: function}
cat2 // Cat {}

// a partial of a function that is used to do some magic redeclaration of props
function foo(Obj) {
    var propNames = Object.keys(Obj);

    // I was missing this if
    // if (propNames.length === 0) {
    //     propNames = Object.getOwnPropertyNames(Obj);
    // }

    for (var prop in propNames) {
        var propName = propNames[prop];

        APIObject[propName] = "reasign/redefine or sth";
    }
}

Так что в моем случае функция foo не сработала, если бы я дал ей объекты типа cat2.

Существуют и другие способы создания объектов, поэтому там могут быть и другие изломы.

Ответ 4

Другое отличие состоит в том, что (по крайней мере, с nodejs) функция "getOwnPropertyNames" не гарантирует порядок ключей, поэтому я обычно использую функцию "keys":

    Object.keys(o).forEach(function(k) {
      if (!o.propertyIsEnumerable(k)) return;
      // do something...
    });