关于javascript:Object.getOwnPropertyNames与Object.keys

Object.getOwnPropertyNames vs Object.keys

JavaScript中Object.getOwnPropertyNamesObject.keys有什么区别? 还可以理解一些示例。


有一点区别。 Object.getOwnPropertyNames(a)返回对象a的所有自身属性。 Object.keys(a)返回所有自己的可枚举属性。这意味着,如果在不使某些对象成为enumerable: false的情况下定义对象属性,则这两种方法将为您提供相同的结果。

很容易测试:

1
2
3
4
5
6
7
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),例如:

1
a.test = 21;

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


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

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


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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
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";
    }
}

因此,在我的情况下,如果我给它赋予cat2类型的对象,则foo函数将不起作用。

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


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

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