On this page
Iterators and Generators
Iterators provide a standard way to produce a sequence of values. Generators are functions that can pause and resume, making iterators easy to create.
Iterable Protocol
An object is iterable if it has a [Symbol.iterator]() method that returns an iterator. Arrays, strings, Maps, and Sets are iterable by default.
let arr = [1, 2, 3];
let iterator = arr[Symbol.iterator]();
console.log(iterator.next()); // { value: 1, done: false }
console.log(iterator.next()); // { value: 2, done: false }
console.log(iterator.next()); // { value: 3, done: false }
console.log(iterator.next()); // { value: undefined, done: true }
for…of
Iterates over iterable values:
for (let char of 'hello') {
console.log(char); // h, e, l, l, o
}
for (let [key, value] of new Map([['a', 1], ['b', 2]])) {
console.log(key, value);
}
Custom Iterable
let range = {
from: 1,
to: 5,
[Symbol.iterator]() {
let current = this.from;
let last = this.to;
return {
next() {
if (current <= last) {
return { value: current++, done: false };
}
return { done: true };
}
};
}
};
for (let n of range) {
console.log(n); // 1, 2, 3, 4, 5
}
Generator Functions
Generators use function* and yield:
function* countUp(max) {
for (let i = 1; i <= max; i++) {
yield i;
}
}
let gen = countUp(3);
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 }
for (let n of countUp(5)) {
console.log(n); // 1 through 5
}
yield* — Delegate to Another Generator
function* inner() {
yield 2;
yield 3;
}
function* outer() {
yield 1;
yield* inner();
yield 4;
}
[...outer()]; // [1, 2, 3, 4]
Passing Values to Generators
function* gen() {
let x = yield 1;
console.log(x); // 'hello'
yield 2;
}
let g = gen();
g.next(); // { value: 1, done: false }
g.next('hello'); // { value: 2, done: false }
Practical Use: Infinite Sequence
function* idGenerator() {
let id = 1;
while (true) {
yield id++;
}
}
const ids = idGenerator();
console.log(ids.next().value); // 1
console.log(ids.next().value); // 2
Practical Use: Lazy Data Processing
function* filter(iterable, predicate) {
for (let item of iterable) {
if (predicate(item)) yield item;
}
}
let evens = filter([1, 2, 3, 4, 5], n => n % 2 === 0);
for (let n of evens) console.log(n); // 2, 4
Generators enable memory-efficient processing of large datasets by producing values on demand rather than building entire arrays in memory.