Generators and Iterators
The Symbol.iterator protocol that powers for...of and spread, and generator functions (function*) as the easiest way to implement it.
function* gen() { yield value; } / obj[Symbol.iterator] = function* () {}
Purpose
An object is iterable if it implements Symbol.iterator, a well-known method returning an
iterator — an object with a .next() method producing { value, done } pairs. This is what
powers for...of and spread for any iterable, not just the built-in arrays/strings/Map/Set. A
generator function (function*) is the easiest way to implement this protocol by hand.
Syntax
function range(start, end) {
return {
[Symbol.iterator]: function* () {
for (let i = start; i < end; i++) {
yield i;
}
},
};
}
for (const n of range(1, 4)) {
console.log(n); // 1, 2, 3
}
function* countUp() {
yield 1;
yield 2;
yield 3;
}
const it = countUp();
it.next(); // { value: 1, done: false }
it.next(); // { value: 2, done: false }
Behavior notes
- Calling a generator function does not run its body — it returns an iterator immediately. The body
only advances, one
yieldat a time, as something pulls values from it. - A generator with an infinite loop containing a
yieldis a normal, useful pattern precisely because of this lazy behavior — nothing runs until a value is actually requested. yieldcan also receive a value passed into.next(value), enabling two-way communication — rarely needed at this level, but the mechanism behind more advanced generator-based patterns.for...of, spread, destructuring, andPromise.all(with an iterable of promises) all rely on the iterable protocol, not on the value specifically being an array.
Common mistakes
- Expecting a generator function’s body to execute immediately upon calling it, the way a normal function does.
- Trying to iterate a generator’s returned iterator a second time — once exhausted (
done: true), it doesn’t reset; a fresh call to the generator function is needed for a new iteration.
Runtime notes
Generators and the iterable protocol are core ECMAScript (ES2015), identical across every current browser and Node version.