Iterators & generator functions

Lazy sequences

Lesson 8 of 20 · 11 min · Module 2: Work with collections

Some sequences are huge or even endless: every page of a feed, every ID ever. Generators produce values one at a time, only when asked, so you never build the whole list.

Start this lesson →

Free. No installation: you write and run the code in your browser, and it is checked automatically.

By the end, you’ll be able to…

  • Write generator functions with yield
  • Iterate with for…of and spread
  • Process endless sequences safely

The idea

A function* is a generator function. yield hands out a value and pauses until the next value is requested. Generators work with for…of, spread, and destructuring, like arrays do.

function* ids() {
  let id = 1;
  while (true) yield id++;
}
const gen = ids();
console.log(gen.next().value, gen.next().value);

01Pause and resume

Each call of next() runs the generator until the next yield and returns { value, done }. The loop variables stay alive between calls.

02Iterables everywhere

Arrays, strings, Maps, Sets and generators are all iterable, so take works with every one of them through the same for…of loop.

const letters = new Set("banana");
console.log([...letters].join(""));
Output
ban

03Errors appear when iterating

A generator body does not run when range(0, 5, 0) is called; it runs on the first next(). That is why the check spreads the result to trigger the RangeError.

Your turn

Write a generator range(start, end, step = 1) that yields numbers from start up to, but not including, end; throw a RangeError when step is not positive. Write take(iterable, n) that returns an array of the first n values of any iterable, including endless ones.

What the checks look for

  • range yields numbers up to the end
  • range rejects a step that is not positive
  • take returns the first values of an array or a string
  • take works with an endless generator
Try it in the editor →

Take this with you

Generators make sequences lazy: values exist only when someone asks.

Go a little further

Write a generator map(iterable, fn) and combine it with take(map(naturals(), n => n * n), 5).

Learn JavaScript Intermediate for free

20 short lessons with real code and instant checks.

See the whole course →