Generators are functions that can be paused and resumed using yield
. They return an iterator that produces values on demand.
function* myGenerator() {
yield 0;
yield 1;
yield 2;
yield 3;
}
const gen = myGenerator();
console.log(gen.next()); // { value: 0, done: false }
console.log(gen.next()); // { value: 1, done: false }
console.log(gen.next()); // { value: 2, done: false }
console.log(gen.next()); // { value: 3, done: false }
console.log(gen.next()); // { value: undefined, done: true }
function* rangeGenerator(start: number, end: number) {
while (start <= end) yield start++;
}
console.log([...rangeGenerator(0, 3)]); // [0, 1, 2, 3]
console.log([...rangeGenerator(5, 10)]); // [5, 6, 7, 8, 9, 10]
yield* [0, 1, 2, 3]
is static, while rangeGenerator
allows any range.[...gen]
) and for...of
.An iterator is an object that follows the Iterator Protocol: it has a next()
method returning { value, done }
.
const myIterator = {
current: 0,
last: 3,
next() {
return this.current <= this.last
? { value: this.current++, done: false }
: { done: true };
}
};
console.log(myIterator.next()); // { value: 0, done: false }
console.log(myIterator.next()); // { value: 1, done: false }
console.log(myIterator.next()); // { value: 2, done: false }
console.log(myIterator.next()); // { value: 3, done: false }
console.log(myIterator.next()); // { done: true }
for...of
)const createIterator = (start: number, end: number) => ({
current: start,
last: end,
next() {
return this.current <= this.last
? { value: this.current++, done: false }
: { done: true };
},
[Symbol.iterator]() {
return this;
}
});
console.log([...createIterator(0, 3)]); // [0, 1, 2, 3]
console.log([...createIterator(5, 10)]); // [5, 6, 7, 8, 9, 10]
Symbol.iterator
makes it work with for...of
, spread
, and Array.from()
.createIterator(5, 10)
produces [5, 6, 7, 8, 9, 10]
.Feature | Generators | Iterators |
---|---|---|
Syntax | function* with yield |
Object with next() |
Lazy Evaluation | Automatic (pause/resume with yield ) |
Manual (explicit control with next() ) |
Iterable (for...of ) |
Yes (automatically iterable) | No, unless Symbol.iterator is implemented |
State Management | Automatic (execution state is saved internally) | Manual (must track current state) |
Best Use Case | Lazy iteration, streaming data, async operations | Custom iteration behavior, strict control over state |