🔄 Iterators & Generators in JavaScript
Iterators and Generators are powerful JavaScript features that allow you to control how data is produced and consumed. They are especially useful for handling large datasets, creating custom loops, and implementing lazy evaluation.
📖 What is an Iterator?
An Iterator is an object that lets you traverse through a collection one item at a time. It exposes a method called next().
Each call to next() returns an object with two properties:
- value → The current value.
- done → true when iteration is complete.
🧠 Iterator Example
Basic Iterator
const arr = [10, 20, 30];
const iterator = arr[Symbol.iterator]();
console.log(iterator.next());
// { value: 10, done: false }
console.log(iterator.next());
// { value: 20, done: false }
console.log(iterator.next());
// { value: 30, done: false }
console.log(iterator.next());
// { value: undefined, done: true }Note
Every array, string, map, and set in JavaScript is already iterable because they implement Symbol.iterator.
⚙️ Creating a Custom Iterator
Custom Iterator
const numbers = {
start: 1,
end: 3,
[Symbol.iterator]() {
let current = this.start;
let last = this.end;
return {
next() {
if (current <= last) {
return {
value: current++,
done: false
};
}
return {
done: true
};
}
};
}
};
for (const num of numbers) {
console.log(num);
}Output:
Output
1
2
3🚀 What are Generators?
A Generator is a special type of function that can pause and resume execution. Instead of returning one value, it can produce multiple values over time.
Generator functions are declared using function* and use theyield keyword.
✨ Basic Generator
Generator Example
function* numbers() {
yield 1;
yield 2;
yield 3;
}
const gen = numbers();
console.log(gen.next());
console.log(gen.next());
console.log(gen.next());
console.log(gen.next());Output:
Output
{ value: 1, done: false }
{ value: 2, done: false }
{ value: 3, done: false }
{ value: undefined, done: true }🎯 Using Generators with for...of
Generator Loop
function* fruits() {
yield "Apple";
yield "Orange";
yield "Banana";
}
for (const fruit of fruits()) {
console.log(fruit);
}🔁 Infinite Generator
Infinite Sequence
function* counter() {
let i = 1;
while (true) {
yield i++;
}
}
const gen = counter();
console.log(gen.next().value);
console.log(gen.next().value);
console.log(gen.next().value);Note
⚠️ Infinite generators never stop by themselves. Always consume them carefully.
📤 Passing Values Back to a Generator
Passing Values
function* greet() {
const name = yield "What's your name?";
yield "Hello " + name;
}
const gen = greet();
console.log(gen.next().value);
console.log(gen.next("John").value);Output:
Output
What's your name?
Hello John⏹ Returning from a Generator
Return Statement
function* demo() {
yield 1;
yield 2;
return 3;
}
const gen = demo();
console.log(gen.next());
console.log(gen.next());
console.log(gen.next());
console.log(gen.next());Output:
Output
{ value: 1, done: false }
{ value: 2, done: false }
{ value: 3, done: true }
{ value: undefined, done: true }⚖️ Iterator vs Generator
| Feature | Iterator | Generator |
|---|---|---|
| Creation | Manual | Automatic with function* |
| State Management | Manual | Handled automatically |
| Syntax | Verbose | Simple |
| Uses yield | ❌ | ✅ |
| Readability | Moderate | Excellent |
💼 Real-World Use Cases
- 📄 Reading large files efficiently.
- 🌐 Processing paginated API responses.
- 📊 Lazy-loading huge datasets.
- 🎮 Game loops and animations.
- 🔄 Custom iterable objects.
- ⚡ Memory-efficient data streams.
🔥 Best Practices
- Use generators for sequences produced on demand.
- Avoid storing huge arrays when a generator can generate values lazily.
- Use for...of to consume iterables cleanly.
- Implement Symbol.iterator for custom iterable objects.
- Be cautious with infinite generators to avoid endless loops.
❌ Common Mistakes
- Calling next() after completion and expecting more values.
- Using yield outside a generator function.
- Forgetting the * in function*.
- Assuming generators execute immediately—they start only when next() is called.
📝 Summary
>>"Iterators define how to traverse data, while Generators provide an elegant way to produce values lazily with minimal code."
Key Takeaways:
- ✅ Iterators expose the next() method.
- ✅ Iterables implement Symbol.iterator.
- ✅ Generators are iterator-producing functions.
- ✅ yield pauses execution and resumes later.
- ✅ Generators simplify complex iteration logic.
- ✅ They are ideal for lazy evaluation and memory-efficient processing.