Object.getOwnPropertyNames与Object.keys


Answers:


289

有一点区别。Object.getOwnPropertyNames(a)返回该对象的所有自身属性aObject.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;

然后,该属性将自动成为可枚举的,并且这两种方法都会产生相同的数组。


26
特别是,length数组对象的属性不可枚举,因此不会显示在中Object.keys
Barmar '16

6
@Barmar length对象的属性在原型上,而不是对象本身,因此Object.keysObject.getOwnPropertyNames不会列出它。
Qodesmith

9
@TheQodesmith的结果Object.getOwnPropertyNames(anyArray)包括length

6
我纠正了!Object.getOwnPropertyNames(anyArray)确实包含length在返回的数组中!
The Qodesmith

是的,但是Array.prototype也有。可以像普通数组一样修改Array.prototype(即Array.prototype.push('whatever')),这有点奇怪。但这似乎对新创建的Array实例没有影响。stackoverflow.com/questions/48020958/…–
trollkotze

21

另一个区别是数组Object.getOwnPropertyNames方法将返回的额外属性length

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

1

创建对象时的文字表示法与构造方法。这是让我着迷的东西。

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类型的对象,该功能将无法正常工作。

还有其他创建对象的方法,因此其中也可能存在其他缺陷。


Object.getOwnPropertyNames将返回属性名的cat1,而不是cat2。创建对象的两种方式在Object.getOwnPropertyNames和之间没有区别Object.keys
Boric

1
@Boric是的,您是正确的。我本来打算同时使用Object.getPrototypeOf(cat2)和这两种方法,而不仅仅是cat2。我不确定,因为我不记得也没有代码。我会在答案中修复它。
h3dkandi

0

如前所述,.keys不会返回可枚举的属性。

关于示例,一个陷阱是一个Error对象:它的某些属性是可枚举的。
因此,尽管console.log(Object.keys(new Error('some msg')))收益率[]console.log(Object.getOwnPropertyNames(new Error('some msg')))收益率["stack", "message"]

console.log(Object.keys(new Error('some msg')));
console.log(Object.getOwnPropertyNames(new Error('some msg')));


-5

另一个区别是(至少与nodejs一起)“ getOwnPropertyNames”函数不能保证键顺序,这就是为什么我通常使用“ keys”函数:

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

1
当前版本的Node.js还是这样getOwnPropertyNames吗?因为ES2015指定的订单Obect.getOwnPropertyNames,而订单的订单Obect.keys仍由实施决定。
szupie

7
我一直以为JS对象键没有顺序,即使实现保留顺序,您也不应该依赖它吗?
Juan Mendes

1
嗯,我想反过来了。getOwnPropertyNames的顺序在规范中定义。Object.keys由实现决定。
tjvr

1
下面的一切都指定顺序:for-in loopObject.keys,和Object.getOwnPropertyNames。就是说,所有三个将以一致的顺序相互列举。
托马斯·爱丁
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.