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...
});