Skip to content

Instantly share code, notes, and snippets.

@rauschma
Last active November 24, 2020 07:14
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save rauschma/fd2518d14a7b1b7b39751d9ac85e6c20 to your computer and use it in GitHub Desktop.
Save rauschma/fd2518d14a7b1b7b39751d9ac85e6c20 to your computer and use it in GitHub Desktop.

for-of, early termination, iterators, and generators

If we terminate a loop early, for-of invokes method .return() of the iterator. Generators return generator objects (that implement both the Iterable interface and the Iterator interface). If we invoke .return() on such an object, the generator is terminated. We can prevent that by overriding .return().

More information: https://exploringjs.com/es6/ch_iteration.html#sec_iteration-protocol-in-depth

Demonstration:

function logIter(iter) {
  console.log('------');
  // First element
  for (const x of iter) {
    console.log(x);
    break;
  }
  // Remaining elements
  for (const x of iter) {
    console.log(x);
  }  
}

//========== .return() stops execution of generator

function* generator1() {
  yield 'a';
  yield 'b';
  yield 'c';
}
const iter1 = generator1();
logIter(iter1);

//========== Overriding .return() so that generator keeps on going

function* generator2() {
  yield 'd';
  yield 'e';
  yield 'f';
}
const iter2 = generator2();
iter2.return = () => {
  console.log('RETURN');
  // Result is only used by yield*
  return {};
};
logIter(iter2);

//========== Array iterators are not affected by .return()

const arr = ['g', 'h', 'i'];
const iter3 = arr[Symbol.iterator]();
logIter(iter3);

//========== Output
// '------'
// 'a'
// '------'
// 'd'
// 'RETURN'
// 'e'
// 'f'
// '------'
// 'g'
// 'h'
// 'i'
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment