Intermediate · Map, Set, iterators, generators and regular expressions · topic 33 of 61 · 25 min
Generators
Explanation
Why generators?
Writing an iterator by hand, as in the last topic, needs an object, a next method and manual state. A generator function writes the same thing as normal-looking code. Each yield hands out one value and pauses the function right there, keeping all its local variables, until the next value is requested.
function* trafficLight() {
yield 'green';
yield 'yellow';
yield 'red';
}
const light = trafficLight(); // nothing runs yet!
console.log(light.next()); // { value: 'green', done: false }
console.log(light.next().value);// 'yellow'
console.log([...trafficLight()]); // ['green', 'yellow', 'red']Calling trafficLight() does not run its body. It returns a generator object. The body runs only when next() is called, and only until the next yield.
Lazy and infinite sequences
Because a generator only works when asked, it can describe an endless sequence. The consumer decides when to stop.
function* orderIds(prefix) {
let n = 1;
while (true) yield `${prefix}-${String(n++).padStart(5, '0')}`;
}
function* take(iterable, count) {
if (count <= 0) return;
for (const x of iterable) {
yield x;
if (--count === 0) return;
}
}
console.log([...take(orderIds('OD'), 3)]); // ['OD-00001', 'OD-00002', 'OD-00003']return and yield*
return inside a generator ends it (done becomes true). yield* other hands out every value of another iterable, which lets generators delegate to each other.
function* menu() {
yield* ['idli', 'dosa'];
yield* ['vada'];
return 'end'; // value of the final { done: true } result
}
console.log([...menu()]); // ['idli', 'dosa', 'vada'] (the return value is not included)Generators as data pipelines
function* filterGen(iter, test) { for (const x of iter) if (test(x)) yield x; }
function* mapGen(iter, fn) { for (const x of iter) yield fn(x); }
const rows = ['12,Asha', 'bad', '7,Ravi'];
const parsed = mapGen(filterGen(rows, (r) => r.includes(',')), (r) => r.split(',')[1]);
console.log([...parsed]); // ['Asha', 'Ravi'] (one row at a time, never all at once)Each step pulls one item through the whole pipeline before the next item is read. For a 5 GB log file read line by line, memory stays small.
Async generators (a preview)
async function* combines generators with promises, and for await…of consumes them. They are ideal for reading a stream of network pages or file chunks. You will learn promises in module 8.
Need help?
Stuck on a word or an idea? Search this course, or every course, and jump straight to the explanation or a worked question.
Try:
Watch the lesson
Generators · 1/6
In this lesson you will write generators, functions that can pause and resume.
Prefer a video by a teacher? Find free videos on “javascript generators yield function* explained” on YouTube ↗
In real life: Generating invoice numbers for the financial year
An accounting tool numbers invoices like INV/2026-27/0001. A generator produces the next number on demand, and the billing code just calls next() each time a bill is saved.
function* invoiceNumbers(fy) {
let n = 1;
while (true) yield `INV/${fy}/${String(n++).padStart(4, '0')}`;
}
const numbers = invoiceNumbers('2026-27');
console.log(numbers.next().value); // INV/2026-27/0001
console.log(numbers.next().value); // INV/2026-27/0002Practice (0/3 done)
Write a generator function countdown(n) that yields n, n - 1, … down to 1.
Write take(iterable, count) as a generator that yields at most count values from any iterable, even an infinite one. Also write naturals() as an infinite generator 1, 2, 3, …
Write a generator fibonacci() that yields 0, 1, 1, 2, 3, 5, … forever. Test code will take only the first few values.
Quick quiz
Read more (free)
Related help
Before this, learn
This topic builds on these. If something here feels new, open them first.
Related topics
- Regular expressions: the basicsMap, Set, iterators, generators and regular expressions · same module
- Map and SetMap, Set, iterators, generators and regular expressions · same module
- Iterators and generatorsPython Programming · Advanced Python
- async and awaitAsynchronous JavaScript
- List, dict and set comprehensionsPython Programming · Working with data
- StreamsFlutter and Dart · Async Dart and packages
Questions people ask about this
Open a question to see the answer and why. The first ones are this topic's own quiz, so try the quiz above before you peek.
What does calling a generator function return?
Answer: A generator object
The body does not run until next() is called.
function* g() { yield 1; return 2; } What is [...g()]?
Answer: [1]
Spread stops at done: true and ignores the return value.
What does yield* [1, 2] do inside a generator?
Answer: Yields 1 then 2
yield* delegates to another iterable, yielding each of its values.
Why can a generator describe an infinite sequence safely?
Answer: It produces values only when asked
Generators are lazy and pause at each yield.
What happens when you call a function that contains yield?Related
Answer: It returns a generator object; the body runs only when values are asked for
Calling a generator function only creates the generator. Each next() runs the body up to the next yield.
What does an iterator's next() return?Related
Answer: An object { value, done }
next() returns { value, done }.
async function f() { return 3; } What is f()?Related
How many items are in {c for c in "banana"}?Related
Pass the quiz (60% or more) or mark this topic as done when you are ready.
Your progress is saved on this device only.
Next steps
- 2 more topics in “Map, Set, iterators, generators and regular expressions” before its exam: Regular expressions: the basics, Regular expressions in practice.
- Module 7 exam: Collections, iterators and regular expressions · 12 questions · 25 min, without help. 5 topics of this module still to finish first.
- Then the next module, Asynchronous JavaScript. 61 topics left in the course before the final exam.