generator functions

They are functions that can be paused at execution and resumed later.
They allow you to generate a sequence of values on-the-fly instead of computing and storing them all at once.

to define a generator function you use the function* keyword.
to pause a generator function you use the yield keyword.

generators follow the iterator protocol, meaning they have

function* foo(index) {
  while (index < 2) {
    yield index;
    index++;
  }
}

const iterator = foo(0);

console.log(iterator.next().value);
// Expected output: 0

console.log(iterator.next().value);
// Expected output: 1