A generator is a JavaScript function that produces values on request rather than all at once. It can pause after producing a value, then resume where it left off with its local variables intact. That makes it useful for sequences—and, when paired with promises, for dependent asynchronous work without blocking the browser UI. section 6.2 section 6.4
Declare one with function* and produce a value with yield. Calling it does not run its body immediately; it creates an iterator. Each iterator.next() runs to the next yield and returns an object with value and done properties. A yielded value pauses execution without blocking the main thread. When the function finishes, done is true. A for-of loop requests the yielded values for you. section 6.2 section 6.2.1
IDs without a global counter
function* ids() { let id = 0; while (true) yield ++id; } const iterator = ids(); iterator.next().value; // 1 iterator.next().value; // 2 The counter belongs to this generator's iterator, so unrelated code cannot change it through a global variable. The infinite loop is manageable here: each call advances only to the next yield. section 6.2.2
Generators can do more than send values out. Pass a value to next(value) to make it the result of the yield expression where execution paused; call iterator.throw(error) to raise an exception inside the generator. Use yield* to delegate part of a sequence to another generator. section 6.2.3 section 6.2.1
Listing 6.7. Iterating over a DOM tree with generators
function* DomTraversal(element){
yield element;
element = element.firstElementChild;
while (element) {
yield* DomTraversal(element); #A
element = element.nextElementSibling;
}
}
const subTree = document.getElementById("subTree");
for(let element of DomTraversal(subTree)) { #B
assert(element !== null, element.nodeName); #B
} #B
Recursive DOM traversal shows why delegation is handy: yield visits the current element, yield* visits each child subtree, and for-of consumes the resulting sequence. section 6.2.2
Under the hood, an iterator moves its generator through a suspended start, execution, a suspended yield, and completion. Its execution context is retained while paused, then reactivated on the next request. For asynchronous tasks, a helper can yield a promise and resume the generator when that promise settles, keeping dependent requests readable without making the requests synchronous. section 6.2.4 section 6.4











