Iterating over an array using for...in
doesn't guarantee order, however ES6 introduces a new construct for...of
.
My limited testing of implementations of for...of
indicates that it does iterate in order on array, but is this property guaranteed?
Yes, the order of for-of
on arrays is guaranteed by the array iterator definition: It will visit the entries in the array in numeric index order (including ones that don't exist, such as those in sparse arrays — or perhaps that should be those not in sparse arrays :-) ):
Here's an example:
"use strict";
const a = [];
a[3] = "d";
a[0] = "a";
a.foo = "f";
for (const v of a) {
console.log(v);
}
Output:
a
undefined
undefined
d
Two things to note above:
Even though the array has an enumerable property foo
, it isn't visited.
The array is sparse, and for-of
did visit the two entries that aren't present (at indexes 1 and 2).
for-in
, however, does not did not have a guaranteed order in ES2015 (aka "ES6") through ES2019; in ES2020, it follows the same property order (with some caveats) as the order-obeying mechanisms added in ES2015 (Object.getOwnPropertyNames
, etc.). Consider this example:
"use strict";
const a = [];
a.foo = "f";
a[3] = "d";
a[0] = "a";
a.bar = "b";
for (const key in a) {
console.log(key);
}
In ES2015 through ES2019, it might output
0
3
foo
bar
or
foo
bar
0
3
or something else.
As of ES2020 and afterward, though, it is specified to output
0
3
foo
bar
because it has to visit the integer index properties first (properties whose names are strings in standard numeric form) in numeric order, followed by other properties in creation order (so, foo
before bar
).
(That assumes there are no enumerable properties on Array.prototype
or Object.prototype
(by default there aren't). If there were, we'd see them as well, but it's not specified where.)
If you want to loop through an array's values, for-of
is a great tool as of ES2015, alongside the other useful tools such as Array#forEach
(forEach
is particularly handy on sparse arrays; it skips the entries that don't exist). for-in
is rarely a good choice. There's an exhaustive list of options in this other answer.