ES6 是否为对象属性引入了明确定义的枚举顺序? [英] Does ES6 introduce a well-defined order of enumeration for object properties?
问题描述
ES6 是否为对象属性引入了明确定义的枚举顺序?
Does ES6 introduce a well-defined order of enumeration for object properties?
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?
推荐答案
注意: 从 ES2020 开始,即使是旧的操作,如 for-in
和 Object.键
需要遵循属性顺序.这并没有改变这样一个事实,即对基本程序逻辑使用属性顺序可能不是一个好主意,因为非整数索引属性的顺序取决于属性的创建时间.
Note: As of ES2020, even older operations like for-in
and Object.keys
are required to follow property order. That doesn't change the fact that using property order for fundamental program logic probably isn't a good idea, since the order for non-integer-index properties depends on when the properties were created.
ES2015-ES2019 的答案:
Answer for ES2015-ES2019:
对于 for-in
、Object.keys
和 JSON.stringify
:否
对于其他一些操作:是,通常.
For some other operations: Yes, usually.
虽然 ES6/ES2015 添加了属性顺序,但它不需要 for-in
、Object.keys
或 JSON.stringify
遵循由于旧版兼容性问题,该顺序是这样的.
While ES6 / ES2015 adds property order, it does not require for-in
, Object.keys
, or JSON.stringify
to follow that order, due to legacy compatibility concerns.
for-in
循环根据 [[Enumerate]],定义为(强调我的):
for-in
loops iterate according to [[Enumerate]], which is defined as (emphasis mine):
当O的[[Enumerate]]内部方法被调用如下采取的步骤:
When the [[Enumerate]] internal method of O is called the following steps are taken:
返回一个迭代器对象(25.1.1.2) 其 next 方法迭代O 的可枚举属性的所有字符串值键.这迭代器对象必须继承自 %IteratorPrototype% (25.1.2).枚举属性的机制和顺序不是指定,但必须符合下面指定的规则[1].
Return an Iterator object (25.1.1.2) whose next method iterates over all the String-valued keys of enumerable properties of O. The Iterator object must inherit from %IteratorPrototype% (25.1.2). The mechanics and order of enumerating the properties is not specified but must conform to the rules specified below [1].
ES7/ES2016 移除了 [[Enumerate]] 内部方法,而是使用抽象操作 EnumerateObjectProperties,但就像 [[Enumerate]] 一样,它没有指定任何顺序.
ES7 / ES2016 removes the [[Enumerate]] internal method and instead uses the abstract operation EnumerateObjectProperties, but just like [[Enumerate]] it doesn't specify any order.
还可以从 Object 中看到这句话.键
:
如果一个实现定义了一个特定的枚举顺序for-in 语句,[...]
If an implementation defines a specific order of enumeration for the for-in statement, [...]
这意味着实现不需要定义特定的枚举顺序.此已被 ECMAScript 项目编辑 Allen Wirfs-Brock 确认2015 语言规范,在规范完成后发表的一篇文章中.
That means implementations are NOT required to define a specific order of enumeration. This has been confirmed by Allen Wirfs-Brock, Project Editor of the ECMAScript 2015 Language Specification, in a post made after the specification was complete.
其他操作,如Object.getOwnPropertyNames
, Object.getOwnPropertySymbols
, Object.defineProperties
和 Reflect.ownKeys
对于普通对象,请遵循以下顺序:
Other operations, like Object.getOwnPropertyNames
, Object.getOwnPropertySymbols
, Object.defineProperties
, and Reflect.ownKeys
do follow the following order for ordinary objects:
- 整数索引(如果适用),按升序排列.
- 其他字符串键(如果适用),按属性创建顺序排列.
- 符号键(如果适用),按属性创建顺序排列.
此行为在 [[OwnPropertyKeys]] 内部方法.但是某些外来对象对内部方法的定义略有不同.例如,代理的 ownKeys
陷阱可能以任何顺序返回一个数组:
This behavior is defined in the [[OwnPropertyKeys]] internal method. But certain exotic objects define that internal method slightly differently. For example, a Proxy's ownKeys
trap may return an array in any order:
console.log(Reflect.ownKeys(new Proxy({}, {
ownKeys: () => ['3','1','2']
}))); // ['3','1','2'], the integer indices are not sorted!
[1] 下面写着:
[[Enumerate]] 必须获取目标对象自己的属性键好像通过调用它的 [[OwnPropertyKeys]] 内部方法.
[[Enumerate]] must obtain the own property keys of the target object as if by calling its [[OwnPropertyKeys]] internal method.
并且 [[OwnPropertyKeys]] 的顺序是明确定义的.但是不要让这让你感到困惑:那个好像"是对的.仅表示相同的属性",而不是相同的顺序".
And the order of [[OwnPropertyKeys]] is well-defined. But don't let that confuse you: that "as if" only means "the same properties", not "the same order".
这可以在 EnumerableOwnNames 中看到,它使用[[OwnPropertyKeys]] 获取属性,然后对它们进行排序
This can be seen in EnumerableOwnNames, which uses [[OwnPropertyKeys]] to get the properties, and then it orders them
与迭代器产生的相对顺序相同如果 [[Enumerate]] 内部方法被调用,将返回
in the same relative order as would be produced by the Iterator that would be returned if the [[Enumerate]] internal method was invoked
如果需要 [[Enumerate]] 以与 [[OwnPropertyKeys]] 相同的顺序进行迭代,则无需重新排序.
If [[Enumerate]] were required to iterate with the same order as [[OwnPropertyKeys]], there wouldn't be any need to reorder.
这篇关于ES6 是否为对象属性引入了明确定义的枚举顺序?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!