Search code examples
javascriptiteratorgeneratorfor-of-loop

Difference between iterator and generator in for of loop in JavaScript


Lets have an iterator and a generator created to working similarly.

What is the reason they behave differently in for of loop if it contains break or return statement?

The generator is finished while the iterator still goes after the end of the loop.

function *createGenerator() { 
  for ( let i=0; i<5; i++ ) {
    yield i;
  }
}

function createIterator() {
  const arr = [1, 2, 3, 4, 5];
  return arr[ Symbol.iterator ]();
}

function runForOfLoopOn( iterable ) {
  for ( const item of iterable ) {
    if ( item == 2 ) { 
      break;
    }
  }
}

const iterator = createIterator();
const generator = createGenerator();

runForOfLoopOn( iterator );
runForOfLoopOn( generator );

console.log( 'Iterator is done:', iterator.next().done );
console.log( 'Generator is done:', generator.next().done );


Solution

  • What happens when a for of loop contains a break or return statement?

    When the body of the loop completes abruptly (with a throw or return statement) or is broken out of, the IteratorClose operation will be called. This which basically amounts to invoking the iterator's .return() method with no arguments if the iterator object has such a method.

    What is the reason an iterator and a generator behave differently?

    That only the generator has such a return() method. The ArrayIterator you created does not have such a method as there is nothing it would need to do. The primary purpose of the return() method is to release resources, e.g. by triggering finally clauses in a generator function, but array iterators don't use any. It could clear its reference to the iterated array (which would be "closing" the iterator), but this was deemed unnecessary as array iterators are typically garbage-collected right away.