Generators & Iterators
Generator functions (function*) return an iterator that produces values lazily via yield. Each call to .next() runs the function body until the next yield, pauses, and returns {value, done}.
A generator is a vending machine with a crank. Each .next() turns the crank once and a snack (value) drops out. The machine pauses between cranks and remembers which row it was on. yield = 'here is your snack, crank me again for the next one.'
Generators implement the iterator protocol ({next(){return {value, done}}}) and the iterable protocol ([Symbol.iterator](){return this}), making them usable in for...of loops, spread, and destructuring. Generators enable lazy sequences (infinite lists), cooperative multitasking, and custom iteration. Two-way communication: .next(valueToSend) passes a value INTO the generator as the result of the yield expression. .throw() and .return() inject errors or completions. yield* delegates to another iterable.
Generators were the foundation of async/await before native support — co, Koa, and redux-saga use generators for async flow control. The generator state machine is captured in the generator object — resuming a generator reconstructs the execution context from the saved state. Generators are pull-based (consumer controls pace); async iterators (for await...of) combine generator semantics with async steps. Infinite generators must be managed carefully: for...of on an infinite generator loops forever. break exits cleanly by calling .return() on the iterator. In performance-critical paths, generators have overhead vs direct iteration — profile before using in hot paths.
Generators are functions that can pause execution at yield points and resume later, enabling lazy evaluation, infinite sequences, and custom iteration protocols. They implement both the iterator and iterable protocols. The key advanced use: generators can receive values via next(val), enabling bidirectional communication. Libraries like redux-saga use this for testable async side effect management.
A generator function call does NOT execute any of the body — it just creates the generator object. The body runs only when .next() is first called. This surprises engineers who expect the code before the first yield to run on generator creation.