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
- Building a lazy, possibly infinite sequence, like an ID generator or a stream of Fibonacci numbers, that only computes the next value when asked.
- Implementing Symbol.iterator on a custom class so instances work directly with for...of and spread syntax.
- Processing a large collection one item at a time instead of building the whole result in memory up front.
- Pausing and resuming a step-by-step process, like paging through an API's results one page per call.