Lazy, pausable functions that let JavaScript produce values on demand — one at a time.
Most JavaScript functions run start to finish and hand back a single value. Generators don't. A function marked with function* can pause itself mid-execution at every yield, hand control back to whoever called it, and pick up exactly where it left off the next time you ask for a value. That's the core trick: instead of computing a whole sequence up front, a generator computes it lazily, one step at a time, only when something actually asks for the next item.
Iterators are the protocol underneath all of this. Any object that implements a next() method returning { value, done } is an iterator, and any object with a Symbol.iterator method that returns one is iterable — which is exactly what powers for...of, spread syntax, and destructuring under the hood. Generators are just the easiest way to build an object that satisfies that protocol without writing the state machine by hand.
What you'll walk away knowing