What is the difference between Reflect.ownKeys(obj) and Obje

What is the difference between Reflect.ownKeys(obj) and Object.keys(obj)?

本文关键字:obj and Obje ownKeys Reflect is the difference between What      更新时间:2023-09-26

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

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

Reflect.ownKeys(obj)何时产生与Object.keys(obj)不同的输出?

Object.keys()返回字符串的array,这些字符串是对象自己的可枚举属性。

Reflect.ownKeys(obj)返回等价于:

Object.getOwnPropertyNames(target).
                   concat(Object.getOwnPropertySymbols(target))

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

首先,一个示例(ES6Iddle):

// 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']

这里,Reflect.ownKeys()返回目标对象自己的属性键的数组。也就是说,直接在给定对象上找到的所有属性(可枚举或不可枚举)的数组与直接在给定物体上找到的全部符号属性的数组相连接。

Object.keys()将只返回可枚举的属性。

可枚举属性是那些可以由for…枚举的属性。。。在循环中,通过原型链继承的属性除外。有关更多详细信息,请参阅MDN说明。

摘要:

Reflect.ownKeys()相当于Object.getOwnPropertyNames(target).concat(Object.getOwnPropertySymbols(target)),它将返回可枚举和不可枚举属性

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

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

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

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

相反,Object.keys调用EnumerableOwnPropertyNames,后者需要:

  1. properties的元素进行排序,使它们的相对顺序与使用O调用EnumerateObjectProperties内部方法时返回的Iterator所产生的相对顺序相同

其中EnumerateObjectProperties显式未指定返回属性的任何顺序:

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

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

(尽管如此,尽管Object.keys、其变体、for..in循环和JSON.stringify都以未指定的、依赖于实现的顺序正式迭代,但幸运的是,环境通常以与Reflect.ownKeys相同的可预测顺序迭代)

  • Object.keys只返回可枚举的字符串键;Reflect.ownKeys返回字符串和符号键,而不管它们的可枚举性如何。两者仅在各自的属性上操作
  • 如果参数不是对象且不是nullundefined(例如Object.keys(1)),则Object.keys返回空数组,而Reflect.ownKeys抛出TypeError
  • Reflect.ownKeys是在ES6中引入的,在较旧的JavaScript引擎中不受支持