ES6是否为对象属性引入了明确定义的枚举顺序?
ES6是否为对象属性引入了明确定义的枚举顺序?
var o = { '1': 1, 'a': 2, 'b': 3 } Object.keys(o); // ["1", "a", "b"] - is this ordering guaranteed by ES6? for(let k in o) { console.log(k); } // 1 2 3 - is this ordering guaranteed by ES6?
For for-in
和Object.keys
: 不。
对于其他一些行动: 是的 ,通常。
虽然ES6 / ES2015添加了属性顺序,但由于传统兼容性问题,它不需要for-in
或Object.keys
来遵循该顺序。
for-in
循环根据[[Enumerate]]迭代,其中[定义为(强调我的)):
当调用O的[[Enumerate]]内部方法时,将采取以下步骤:
返回一个Iterator对象( 25.1.1.2 ),它的下一个方法迭代O的所有可枚举属性的String值。 Iterator对象必须从%IteratorPrototype%( 25.1.2 )继承。 枚举属性的机制和顺序 没有指定,但必须符合下面指定的规则[1] 。
ES7 / ES2016删除了[[Enumerate]]内部方法,而是使用抽象操作EnumerateObjectProperties ,但是就像[[Enumerate]]一样,它没有指定任何顺序。
还可以从Object.keys
看到这个引用:
如果一个实现定义了for-in语句的特定枚举顺序,
这意味着实现不需要定义枚举的特定顺序 。 ECMAScript 2015语言规范的项目编辑Allen Wirfs-Brock在规范完成后的一篇文章中已经证实了这一点 。
其他操作,如Object.getOwnPropertyNames
, Object.getOwnPropertySymbols
和Reflect.ownKeys
,按照以下顺序为普通对象:
- 整数索引(如果适用),按升序排列。
- 其他字符串键(如果适用),属性创建顺序。
- 符号键(如果适用),属性创建顺序。
此行为在[[OwnPropertyKeys]]内部方法中定义。 但是请注意, 异域对象可能会以不同方式定义该方法,例如
console.log(Reflect.ownKeys(new Proxy({}, { ownKeys: () => ['3','1','2'] }))); // ['3','1','2'], the integer indices are not sorted!