Object.getOwnPropertyNames 与 Object.keys

IT技术 javascript
2021-01-18 05:38:34

Object.getOwnPropertyNamesObject.keys在 javascript 中有什么区别还有一些例子将不胜感激。

5个回答

有一点不同。Object.getOwnPropertyNames(a)返回对象的所有自己的属性aObject.keys(a)返回所有可枚举的自己的属性。这意味着如果你定义你的对象属性而不创建它们中的一些,enumerable: false这两种方法会给你相同的结果。

测试很容易:

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

如果您定义了一个属性而不提供属性属性描述符(意味着您不使用Object.defineProperties),例如:

a.test = 21;

那么这样的属性会自动成为可枚举的,并且两种方法都会生成相同的数组。

特别length是数组对象属性是不可枚举的,所以它不会出现在Object.keys.
2021-03-15 05:38:34
@TheQodesmithObject.getOwnPropertyNames(anyArray)包含的结果length
2021-03-20 05:38:34
@Barmarlength对象属性在原型上,而不是对象本身,因此既Object.keys不会也Object.getOwnPropertyNames不会列出它。
2021-03-24 05:38:34
我站纠正!Object.getOwnPropertyNames(anyArray)确实包含length在返回的数组中!
2021-03-24 05:38:34
是的,但 Array.prototype 也有。可以像普通数组一样修改 Array.prototype(即 Array.prototype.push('whatever')),这有点奇怪。但它似乎对新创建的 Array 实例没有影响。stackoverflow.com/questions/48020958/...
2021-04-12 05:38:34

另一个区别是在数组Object.getOwnPropertyNames方法的情况下将返回一个额外的属性,即length.

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

创建对象时的文字符号与构造函数。这是让我着迷的东西。

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和 not的属性名称cat2创建对象的两种方式不会在Object.getOwnPropertyNames之间产生差异Object.keys
2021-03-20 05:38:34
@Boric 是的,你是对的。我本可以将 Object.getPrototypeOf(cat2) 与这两种方法一起使用,而不仅仅是 cat2。我不能确定,因为我不记得也没有代码。我会在答案中修复它。
2021-03-24 05:38:34

正如已经解释过的,.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')));

另一个区别是(至少对于 nodejs)“getOwnPropertyNames”函数不保证键顺序,这就是我通常使用“键”函数的原因:

    Object.keys(o).forEach(function(k) {
      if (!o.propertyIsEnumerable(k)) return;
      // do something...
    });
嗯,我认为情况正好相反;getOwnPropertyNames 的顺序在规范中定义。Object.keys 取决于实现。
2021-03-16 05:38:34
在当前版本的 Node.js 中是否仍然如此,如果是,您是否知道任何getOwnPropertyNames不正常的示例因为 ES2015 指定了 for 的顺序Obect.getOwnPropertyNames,而for顺序Obect.keys还是要看实现。
2021-03-19 05:38:34
下面的一切都指定顺序:for-in loopObject.keys,和Object.getOwnPropertyNames也就是说,所有三个都将以一致的顺序相互枚举。
2021-03-20 05:38:34
我一直认为 JS 对象键没有顺序,即使实现保持顺序,你也不应该依赖它?
2021-04-07 05:38:34