← All concepts
Beyond the Course

Iterators and Generators

A generator writes a pausable, resumable function that hands out one value at a time.

Loading visual…

Definition

An iterator is any object with a `next()` method that returns `{ value, done }`: `value` is the next item, and `done` is true once there is nothing left. An object is iterable if it implements `Symbol.iterator`, a method that returns an iterator, which is what lets it work with `for...of`, spread syntax, and destructuring. Arrays, strings, Maps, and Sets are all built-in iterables. A generator function, written with `function*`, is a shortcut for building an iterator by hand. Calling it does not run the function body; it returns a generator object, which is itself an iterator. Each call to that generator's `next()` runs the body forward until it hits a `yield` expression, at which point execution pauses, the yielded value comes back as `{ value, done: false }`, and every local variable's state is preserved exactly where it left off. The next call to `next()` resumes right after that `yield` and runs until the next one, or until the function returns, which produces `{ value: returnValue, done: true }`. Because a generator only computes the next value when asked, it can represent lazy or even infinite sequences, like a counter that yields forever, without ever running out of memory.

Examples

function* count() {
  let i = 0;
  while (true) yield i++;
}
const it = count();
it.next(); // { value: 0, done: false }
it.next(); // { value: 1, done: false }

Each next() call resumes count() right after its last yield, hands back the current i, and pauses again, with i preserved between calls.

function* upTo(n) {
  for (let i = 1; i <= n; i++) yield i;
}
[...upTo(3)]; // [1, 2, 3]

Spreading a generator drains it by calling next() until done is true, collecting every yielded value into an array.

Where you see this

Practice this

Further reading