100% Free Forever
AI-Powered Learning
Industry Expert Content
Certificates & Badges
Learn At Your Own Pace

What Are Generators in JavaScript and How Do They Work?

Learn how JavaScript generators pause and resume with yield, implement iterables, and enable lazy sequences with real code examples.

hardQ38 of 224 in Web Development Est. time: 6 minsLast updated:
Open Code Lab

Expected Interview Answer

A generator is a special function, declared with function*, that can pause its own execution at yield points and resume later exactly where it left off, producing a sequence of values lazily over multiple calls instead of computing and returning them all at once.

Calling a generator function does not run its body immediately; instead it returns an iterator object. Each call to that iterator’s next() method runs the generator body until it hits a yield expression, at which point execution pauses, the yielded value is returned wrapped as { value, done: false }, and the entire local state — variables, call stack position — is preserved. Calling next() again resumes exactly after that yield, optionally injecting a value into the paused expression, and continues until the next yield or a return, which produces { value, done: true }. Because generators implement the iterable protocol, they can be consumed directly with for...of, spread syntax, or destructuring. This pause-and-resume mechanism makes generators ideal for lazily producing infinite or large sequences without pre-computing them, for implementing custom iterators cleanly, and historically for writing asynchronous code that reads like synchronous code (the basis for how libraries implemented async/await before it was native, via yielding promises to a driver function).

  • Produces values lazily, on demand, avoiding pre-computing entire large or infinite sequences
  • Preserves local execution state across pauses without manual state machines
  • Implements the iterable protocol automatically, working with for...of and spread
  • Enables two-way communication via next(value) passed back into the paused yield expression

AI Mentor Explanation

A generator is like a bowler who delivers one ball, then pauses at the top of their mark until the umpire signals for the next delivery, rather than bowling an entire over in one uninterrupted burst. Each time play resumes, the bowler picks up exactly where they left off, remembering their run-up rhythm and field placements from before the pause. The umpire can even relay information back to the bowler between deliveries, subtly changing the next ball bowled. That pause-resume-with-preserved-state-and-two-way-signal cycle is exactly how a JavaScript generator’s yield and next() work.

Step-by-Step Explanation

  1. Step 1

    Define with function*

    Mark the function with an asterisk to make it a generator function.

  2. Step 2

    Call returns an iterator

    Invoking the generator does not run the body; it returns a generator object implementing the iterator protocol.

  3. Step 3

    next() runs until yield

    Each next() call executes code until a yield expression, pausing and returning { value, done: false }.

  4. Step 4

    Resume or complete

    Subsequent next() calls resume exactly after the last yield until a return produces { value, done: true }.

What Interviewer Expects

  • Correct explanation of function* syntax and the returned iterator object
  • Understanding that execution truly pauses and resumes, preserving local state
  • Awareness that generators implement the iterable protocol (for...of, spread)
  • Knowledge of next(value) injecting data back into a paused yield expression

Common Mistakes

  • Believing calling a generator function executes its body immediately
  • Confusing yield with return, not realizing yield pauses rather than exits
  • Forgetting generators are iterable and trying to consume them incorrectly
  • Not knowing next(value) can pass data back into the paused expression

Best Answer (HR Friendly)

A generator is a special kind of function that can pause itself midway through and pick up again later exactly where it stopped, instead of running start to finish in one go. This makes it great for producing values one at a time, like an endless counter or a lazy list, without computing everything upfront.

Code Example

A generator producing an infinite lazy sequence
function* idGenerator() {
  let id = 1
  while (true) {
    const reset = yield id // pauses here, can receive a value via next()
    id = reset ? 1 : id + 1
  }
}

const gen = idGenerator()
console.log(gen.next().value) // 1
console.log(gen.next().value) // 2
console.log(gen.next(true).value) // reset -> 1

// Generators are iterable
function* firstThree() {
  yield 'a'
  yield 'b'
  yield 'c'
}
for (const letter of firstThree()) {
  console.log(letter) // 'a', then 'b', then 'c'
}

Follow-up Questions

  • How do generators differ from async/await, and how were they used to build async/await-like behavior before it existed?
  • What does yield* do when delegating to another generator?
  • How would you implement an infinite Fibonacci sequence using a generator?
  • What is the difference between a generator object and a plain iterator you implement manually?

MCQ Practice

1. What does calling a generator function return?

Calling a generator function returns an iterator; execution only begins on the first next() call.

2. What does a yield expression do when the generator body reaches it?

yield pauses execution at that point, preserving all local state until the next next() call resumes it.

3. How can you pass a value back into a paused generator?

next(value) resumes the generator, and value becomes the evaluated result of the yield expression that was paused.

Flash Cards

How do you declare a generator function?With an asterisk: function* name() { ... }.

What does calling a generator function return?An iterator object; the body does not run until next() is called.

What does yield do?Pauses execution, returns the yielded value, and preserves local state until resumed.

How do you send a value into a paused generator?Call next(value) — it becomes the result of the paused yield expression.

1 / 4

Continue Learning