Iterators and Generators in JavaScript
Iterators define a standard way to step through data; generators make writing iterators easy.
Iterator protocol
An object is iterable if it has [Symbol.iterator]() returning an iterator with next().
const iter = {
current: 0,
[Symbol.iterator]() { return this },
next() {
if (this.current < 3) return { value: this.current++, done: false }
return { value: undefined, done: true }
}
}
for (const v of iter) {}
Generators
Use function* and yield to create iterators.
function* count(n) {
for (let i = 0; i < n; i++) yield i
}
[...count(3)] // [0,1,2]
Generator communication
next(value) sends a value back to the generator; return ends it; throw injects an error.
Async iterators
Use async function* with for await..of for streams of promises.
async function* lines(stream) {
for await (const chunk of stream) {
yield* chunk.split('\n')
}
}
Built-ins and helpers
- Many built-ins are iterable: arrays, strings, maps, sets
- Use spread (
...iterable) and array from (Array.from(iterable)) to collect
Summary
- Implement the iterator protocol or use generators for custom sequences
- Use async generators and
for await..offor asynchronous streams