Reflect.ownKeys(obj)和Object.keys(obj)有什么区别?

m0m*_*eni 44 javascript ecmascript-6 es2015

在一个真实的简单案例中测试它们会产生相同的输出:

const obj = {a: 5, b: 5};
console.log(Reflect.ownKeys(obj));
console.log(Object.keys(obj));

// Result
['a', 'b']
['a', 'b']
Run Code Online (Sandbox Code Playgroud)

什么时候Reflect.ownKeys(obj)产生的输出不同Object.keys(obj)

Bat*_*eam 42

Object.keys()返回一个array字符串,它是对象自己的可枚举属性.

Reflect.ownKeys(obj) 返回相当于:

Object.getOwnPropertyNames(target).
                   concat(Object.getOwnPropertySymbols(target))
Run Code Online (Sandbox Code Playgroud)

Object.getOwnPropertyNames()方法返回直接在给定对象上找到的所有属性(或不属性)的数组.enumerable

Object.getOwnPropertySymbols()方法返回symbol直接在给定对象上找到的所有属性的数组.

var testObject;
Object.defineProperty(testObject, 'myMethod', {
    value: function () {
        alert("Non enumerable property");
    },
    enumerable: false
});

//does not print myMethod since it is defined to be non-enumerable
console.log(Object.keys(testObject));   

//prints myMethod irrespective of it being enumerable or not.
console.log(Reflect.ownKeys(testObject)); 
Run Code Online (Sandbox Code Playgroud)

小小的fiddle证明.

  • 有这个用吗? (2认同)
  • 它也是键和符号之间的重要区别,它可能需要也可能不需要枚举为两个不同的东西 (2认同)

Jos*_*ham 12

首先,一个例子(ES6Fiddle):

// getFoo is property which isn't enumerable
var my_obj = Object.create({}, { getFoo: { value: function() { return this.foo; } } });
my_obj.foo = 1;

console.log(Object.keys(my_obj)); // console ['foo']
console.log(Reflect.ownKeys(my_obj)); // console ['getFoo', 'foo']
Run Code Online (Sandbox Code Playgroud)

这里,Reflect.ownKeys()返回目标对象自己的属性键的数组.即,直接在给定对象上找到的所有属性(可枚举或不可枚举)的数组与直接在给定对象上找到的所有符号属性的数组连接.

Object.ownKeys() 只会返回可枚举的属性.

可枚举属性是可以通过for ... in循环枚举的属性,但通过原型链继承的属性除外.有关更多详细信息,请参阅MDN说明.

摘要:

Reflect.ownKeys()等效于Object.getOwnPropertyNames(target).concat(Object.getOwnPropertySymbols(target))返回可枚举和不可枚举的属性

Object.keys()返回可枚举属性,但不返回非可枚举属性(这是Object.getOwnPropertyNames()的一个特征).


GOT*_*O 0 5

  • Object.keys只返回可枚举的字符串键; Reflect.ownKeys无论其可枚举性如何,都返回字符串和符号键.两者都仅在自己的属性上运行.
  • Object.keys如果参数不是对象而不是nullundefined(例如Object.keys(1)),则返回一个空数组,而Reflect.ownKeys抛出a TypeError.
  • Reflect.ownKeys 是在ES6中引入的,旧的JavaScript引擎不支持.


Cer*_*nce 5

除了其他答案已经提到的内容之外,规范Reflect.ownKeys保证按以下顺序返回键(和符号):

  • 整数数字键,按升序排列 (0, 1, 2)
  • 字符串键,按照它们插入对象的顺序
  • 符号键

[[OwnPropertyKeys]]调用的内部方法需要此顺序 Reflect.ownKeys

相比之下,Object.keys调用EnumerableOwnPropertyNames,这需要:

  1. 对 的元素进行properties排序,使它们的相对顺序与迭代器生成的相对顺序相同,如果使用 O 调用EnumerateObjectProperties内部方法,则返回的迭代器将返回。

其中EnumerateObjectProperties明确没有指定返回属性的任何顺序:

未指定枚举属性的机制和顺序

因此,如果您想绝对确定,在迭代对象属性时,您按插入顺序对非数字键进行迭代,请确保使用Reflect.ownKeys(or Object.getOwnPropertyNames,它也调用[[OwnPropertyKeys]])。

(总而言之,whileObject.keys及其变体、for..in循环和JSON.stringify所有正式以未指定的、依赖于实现的顺序进行迭代Reflect.ownKeys,幸运的是,环境通常以与任何方式相同的可预测顺序进行迭代)