Syntax
function* generatorName() {
yield value;
}Examples
Basic Generator Function
A generator that produces values lazily, one at a time.
function* countUpTo(max) {
for (let i = 1; i <= max; i++) {
yield i;
}
}
const counter = countUpTo(3);
console.log(counter.next()); // { value: 1, done: false }
console.log(counter.next()); // { value: 2, done: false }
console.log(counter.next()); // { value: 3, done: false }
console.log(counter.next()); // { value: undefined, done: true }Using Generators with for...of
Generators are iterable, so they work directly with for...of and spread.
function* fruits() {
yield "apple";
yield "banana";
yield "cherry";
}
for (const fruit of fruits()) {
console.log(fruit);
}
// apple, banana, cherry
console.log([...fruits()]); // ["apple", "banana", "cherry"]Custom Iterable Object
Making any object work with for...of by implementing Symbol.iterator.
const range = {
from: 1,
to: 5,
[Symbol.iterator]() {
let current = this.from;
const last = this.to;
return {
next() {
if (current <= last) {
return { value: current++, done: false };
}
return { value: undefined, done: true };
}
};
}
};
for (const num of range) {
console.log(num); // 1, 2, 3, 4, 5
}Best practices
- Use generators for lazily-computed sequences, especially large or potentially infinite ones, since values are only produced as they are requested
- Prefer generators over manually managing iterator state objects - the syntax is far more readable
- Remember a generator function returns an iterator when called - it does not run its body immediately
- Reach for this pattern when building custom data structures (like a tree or linked list) that should support for...of
Runtime & versions
Browsers and JavaScript runtimes. Feature availability depends on the language and runtime version used by your project; consult the official reference below.
ECMAScript specification