Search code examples
javascriptiteratoriterablefor-of-loop

Is iterating with for..of loop over iterator instead of iterable is legal?


The recommended way of iterating over an iterable object is with for..of loop over the object itself like this:

const a = [ 'one', 'two', 'three' ];
for(const item of a)
  console.log(item);

I have been experimenting with iterating and found out that the following also works with exactly the same result:

const a = [ 'one', 'two', 'three' ];
let iter = a[Symbol.iterator]();
for(const item of iter)
  console.log(item);

And even this works:

const a = [ 'one', 'two', 'three' ];
let iter = a[Symbol.iterator]();
let iter2 = iter[Symbol.iterator]();
for(const item of iter2)
  console.log(item);

Regarding for..of loop, I did not see recommendations to iterate over iterator instead of iterable. See, for example, for..of in MDN.

Is it legal to iterate this way?


Solution

  • for..of assumes an Iterable (something that has Symbol.iterator) see https://262.ecma-international.org/11.0/#sec-runtime-semantics-forinofheadevaluation, point 7.

    When you pass a built-in Iterator, like StringIterator or ArrayIterator, it's no problem, because for butil-in Iterators (which inherit from IteratorPrototype) Symbol.iterator just returns itself (https://262.ecma-international.org/11.0/#sec-%iteratorprototype%-@@iterator).

    User-defined iterators are not guaranteed to obey this rule, but it's a good practice to design them like this.