JavaScript usually runs code from top to bottom.
Generators change that by allowing functions to **pause and resume**.
This makes them ideal for iterators, streams, and lazy evaluation.
## 🔹 What Is an Iterator?
An iterator is an object with a `next()` method that returns:
```js
{ value: any, done: boolean }
Arrays, strings, and maps already implement iterators.
🔹 What Is a Generator?
A generator is a special function:
• Declared with function*
• Uses yield to pause execution
• Returns an iterator automatically
function* countUp() {
let i = 0;
while (true) {
yield i++;
}
}
🔹 Using a Generator
const counter = countUp();
counter.next().value; // 0
counter.next().value; // 1
counter.next().value; // 2
Execution resumes exactly where it paused.
🔹 Generators in for...of
function* range(start, end) {
for (let i = start; i <= end; i++) {
yield i;
}
}
for (const n of range(1, 3)) {
console.log(n);
}
Output:
1
2
3
🔹 Why Generators Are Powerful
Generators enable:
• Lazy data processing
• Infinite sequences
• Custom iteration logic
• Cleaner async patterns (historically)
🔹 Generator vs Normal Function
|Feature Function Generator
|Pause execution ❌ ✅
|Resume execution ❌ ✅
|Returns iterator ❌ ✅
|Uses yield ❌ ✅
🔹 Common Use Cases
• Pagination
• Parsing streams
• State machines
• Data pipelines
🔹 Common Mistakes
❌ Forgetting * in function*
❌ Expecting generators to run automatically
❌ Using generators where simple arrays suffice
🔹 Best Practices
• Use generators for lazy workflows
• Keep generator logic simple
• Combine with for...of
✅ Recommended:
function* ids() {
let id = 1;
while (true) yield id++;
}
🎯 Final Thought
Generators turn execution into a conversation,
not a one-way script.
Step-by-step control leads to elegant solutions.