Heptic Heptic - 3 months ago 13
Javascript Question

Does "for...of" loop iteration follow the array order in JavaScript?

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?

Answer

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

Live Example on Babel's REPL, and here's an on-site snippet for those using an up-to-date browser:

"use strict";
let a = [];
a[3] = 'd';
a[0] = 'a';
a.foo = "f";
for (let v of a) {
  console.log(v);
}

Output:

a
undefined
undefined
d

(The two undefineds show as blank in Babel's REPL.)

Two things to note above:

  1. Even though the array has an enumerable property foo, it isn't visited.

  2. 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 have a guaranteed order, not even in ES2015 (aka "ES6"). It's really easy to read the spec such that it does, but it doesn't; see this answer for details. Also note that using for-in on arrays will not only visit the "indexes" of the arrays, but all of the array's enumerable property names, including non-index property names. So for example, even in ES2015, this:

"use strict";
var a = [];
a.foo = "f";
a[3] = 'd';
a[0] = 'a';
a.bar = "b";
var key;
for (key in a) {
  console.log(key);
}

...might output:

0
3
foo
bar

...or

foo
bar
0
3

...or something else, although it's very likely with the current set of JavaScript implementatoins (but not required by the spec) that the all-digits keys ("indexes") will be grouped together, either before or after the other properties.

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.

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.

Comments