Generators & Iterators

Learn how to write functions that can pause their own execution mid-way through, yielding values one at a time on demand.

JavaScript7 min readConcept 49 of 62

The Pausable Function

A standard JavaScript function runs from top to bottom, without stopping, until it hits a return statement or the end of the block.

**Generators** are special functions (declared with an asterisk function*) that can be paused in the middle of execution and resumed later. They do this using the yield keyword.

Lazy Evaluation

Why would you want to pause a function?

Imagine you need to generate a sequence of 1,000,000 unique IDs. If a normal function did this, it would lock up the browser while it calculated and stored all 1,000,000 IDs in memory at once.

A Generator can generate exactly *one* ID, yield it to the caller, and then go to sleep. It only generates the next ID when the caller explicitly asks for it. This is called 'lazy evaluation' and is incredibly memory efficient.

Iterators and next()

When you call a generator function, it doesn't run the code inside. Instead, it returns an **Iterator** object.

javascript function* counter() { yield 1; yield 2; } const gen = counter();

To actually run the code, you must call gen.next(). The function wakes up, runs until it hits the first yield 1, and then pauses. gen.next() returns an object: { value: 1, done: false }.

If you call gen.next() again, it resumes where it left off, hits yield 2, and returns { value: 2, done: false }. Calling it a third time returns { value: undefined, done: true }.

The Yield Pipeline

Study the architecture diagram below. It illustrates the exact mechanical relationship between the Generator code, the Iterator object, and the flow of .next() calls pulling values from yield statements.

The Yield Pipeline

// 1. The Generator Factoryfunction* counter() {
yield 1;
yield 2;
}
// 2. Executionconst gen = counter();
↳ Returns a paused Iterator objectgen.next();
↳ Wakes up, yields 1, pauses. { value: 1, done: false }gen.next();
↳ Resumes, yields 2, pauses. { value: 2, done: false }gen.next();
↳ Resumes, finishes. { value: undefined, done: true }
1. const gen = counter()
State:<Iterator> (Paused)
2. gen.next()yield 1
Returns:{ value: 1, done: false }
3. gen.next()yield 2
Returns:{ value: 2, done: false }
4. gen.next()finished
Returns:{ value: undefined, done: true }
iA Generator never executes upon being called. It returns a paused Iterator. It only wakes up and executes code when you actively pull on it by calling .next()!

Check yourself

Pick an answer to lock it in, then read why. Getting one wrong is part of how it sticks.

  1. 1What does calling a generator function like `myGenerator()` immediately return?
  2. 2What is the shape of the object returned when you call `.next()` on an iterator?
  3. 3How can a Generator be highly memory-efficient when working with massive datasets?

Remember this

  • Generators are declared with function* and can pause execution using yield.
  • Calling a generator function returns a paused Iterator object, it does not run the code inside.
  • Use .next() to wake the generator up and pull the next value.
  • .next() returns an object shaped like { value: data, done: boolean }.
  • Generators are excellent for memory-efficient lazy evaluation and infinite sequences.

Done with this concept?

Mark it complete to track your progress. No login needed.