'Does ES6 introduce a well-defined order of enumeration for object properties?
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?
Solution 1:[1]
As covered in the other answer, ES2015 does not define enumeration order for the (very commonly used) property iteration methods for-in, Object.keys, and JSON.stringify, whereas it does define enumeration methods for other methods like Reflect.ownKeys. However, this inconsistency will soon no longer exist, and all property iteration methods will iterate in a predictable manner.
As many have probably observed in their own experience with JS and in the comments, although property iteration order is not guaranteed by the specification for those methods above, every implementation almost always iterates in the same deterministic order anyway. As a result, there is a (finished) proposal to change the specification to make this behavior official:
Specifying for-in enumeration order (Stage 4)
With this proposal, under most circumstances, for..in, Object.keys / values / entries, and JSON.stringify are guaranteed to iterate in order over:
(1) Numeric array keys
(2) non-Symbol keys, in insertion order
(3) Symbol keys, in insertion order
Which is the same order as with Reflect.ownKeys and the other methods which are already guaranteed to iterate this way.
The specification text is rather simple: EnumerateObjectProperties, the problematic abstract method invoked by for..in, etc, whose order used to be unspecified, will now call [[OwnPropertyKeys]], which is the internal method for which iteration order is specified.
There are a few weird cases which implementations currently do not agree on, and in such cases, the resulting order will continue be unspecified, but such cases are few and far between.
Solution 2:[2]
This question is about EcmaScript 2015 (ES6). But it should be noted that the EcmaScript2017 specification has removed the following paragraph that previously appeared in the specification for Object.keys, here quoted from the EcmaScript 2016 specification:
If an implementation defines a specific order of enumeration for the for-in statement, the same order must be used for the elements of the array returned in step 3.
Furthermore, the EcmaScript 2020 specification removes the following paragraph from the section on EnumerableOwnPropertyNames, which still appears in the EcmaScript 2019 specification:
- Order the elements of properties so they are in the same relative order as would be produced by the Iterator that would be returned if the EnumerateObjectProperties internal method were invoked with O.
These removals mean that from EcmaScript 2020 onwards, Object.keys enforces the same specific order as Object.getOwnPropertyNames and Reflect.ownKeys, namely the one specified in OrdinaryOwnPropertyKeys. The order is:
- Own properties that are array indexes,1 in ascending numeric index order
- Other own String properties, in ascending chronological order of property creation
- Own Symbol properties, in ascending chronological order of property creation
1 An array index is a String-valued property key that is a canonical numeric String2 whose numeric value i is an integer in the range +0 ? i < 232 - 1.
2 A canonical numeric String is a String representation of a Number that would be produced by ToString, or the string "-0". So for instance, "012" is not a canonical numeric String, but "12" is.
It should be noted that all major implementations had already aligned with this order years ago.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | |
| Solution 2 |
