Free tools Windows power users keep installed

One-click scans. No signup required.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

A JavaScript generator function pauses at yield and continues only when its caller asks for another value. Writing it as function* and calling it creates a generator object—not an immediately running function result. Each call to next() resumes execution and returns an object with value and done fields.

What a generator function does

A generator function is a function that can suspend and resume its execution. The asterisk in function* marks the declaration:

function* countUpTo(limit) {
  for (let value = 1; value <= limit; value++) {
    yield value;
  }
}

const iterator = countUpTo(3);
console.log(iterator.next()); // { value: 1, done: false }
console.log(iterator.next()); // { value: 2, done: false }
console.log(iterator.next()); // { value: 3, done: false }
console.log(iterator.next()); // { value: undefined, done: true }

Calling countUpTo(3) creates a generator object, which remembers where execution is paused and the function’s local state. The body starts running when next() is called. Each call continues until the next yield or until the function finishes. The generator object follows the iterator and iterable protocols, so it works both with direct calls to next() and with constructs such as for...of and array spread. See MDN’s iterators and generators guide and function* reference.

How to read an iterator result

Every next() call returns an object with two fields:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
  • value is the value yielded by the generator, or its final return value when it completes.
  • done is false while the generator can continue and true when it has finished.

In the example, each yielded number arrives with done: false. Once the loop ends, the generator reports done: true; because the function did not explicitly return a value, the final value is undefined.

How yield pauses and resumes execution

The yield operator pauses the generator and makes the expression’s value available to the caller. When the caller resumes the generator, the suspended yield expression evaluates to the argument passed to next(). MDN describes yield as an operator used “to pause and resume a generator function” in its yield reference.

function* conversation() {
  const answer = yield "What is your name?";
  yield `Hello, ${answer}`;
}

const chat = conversation();
console.log(chat.next());       // { value: "What is your name?", done: false }
console.log(chat.next("Ada")); // { value: "Hello, Ada", done: false }
console.log(chat.next());       // { value: undefined, done: true }

The first next() starts the function and reaches the first yield, which produces the question. The next call passes "Ada" into that suspended yield expression, so answer becomes "Ada". This is why next() has two roles: its returned object carries a value out, while its optional argument sends a value in.

An argument to the first next() call is ignored. At that point the generator has not started and no suspended yield is waiting to receive it.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

How yield* delegates to another iterable

Use yield* when a generator should pass through values from another iterable rather than yield them one by one itself. The outer generator delegates iteration to that iterable, which can be another generator:

function* first() {
  yield "red";
  yield "green";
}

function* allColors() {
  yield* first();
  yield "blue";
}

console.log([...allColors()]); // ["red", "green", "blue"]

Here, the spread syntax consumes allColors(), and the delegated colors appear in sequence before "blue". Delegation can also forward iterator operations to the delegated iterator. See MDN’s yield* reference.

How generators compare with ordinary functions and arrays

Comparison Generator Ordinary function or eager array
Execution timing A call creates a generator object; its body advances when the consumer requests values. An ordinary function runs when called. An eager array’s values are already computed when the array is created.
What the consumer receives Direct calls to next() return iterator-result objects with value and done. An ordinary function returns its result directly; an array stores its elements.
How values are produced One at a time as requested; the generator retains its execution state between yields. An array is built as a whole rather than generated on demand.

This demand-driven behavior makes generators useful for sequences that are large, incremental, or potentially infinite. It does not establish a fixed speed or memory advantage: the practical result depends on the work being done and how the values are consumed.

Example: stop consuming an infinite sequence

function* integers() {
  let value = 0;
  while (true) yield value++;
}

for (const value of integers()) {
  if (value === 3) break;
  console.log(value);
}

The generator can describe an unbounded sequence without creating an unbounded array. The loop requests values as it runs and stops when it reaches 3, so it never asks the generator for later values.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

How return() and throw() control a generator

Generator objects expose next(), return(), and throw(). These are iterator control methods, not ways to restart a generator.

  • return(value) requests completion as if a return were inserted at the generator’s suspended position.
  • throw(error) injects an error at the suspended position. Generator code can catch it, or it can escape to the caller.

A try...finally block can run cleanup when a generator is closed:

function* withCleanup() {
  try {
    yield "working";
  } finally {
    console.log("cleanup");
  }
}

const task = withCleanup();
task.next();
task.return(); // runs finally before closing

After a generator has completed, it does not resume producing later yields.

How async generators differ

An async generator is declared with async function*. Unlike a regular generator, its next() method returns a promise that resolves to an iterator result. Consume its values with for await...of:

What’s actually slowing this PC down?

Pick the symptom - the matching free tool is one click away.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
async function* pages() {
  yield "page one";
  yield "page two";
}

for await (const page of pages()) {
  console.log(page);
}

The async keyword marks a distinct generator form; a regular function* is not automatically asynchronous. The behavior described here follows the JavaScript language references maintained by MDN and the Generator reference; the normative language specification checked is Ecma International’s ECMA-262, 16th edition, published June 2025. MDN’s yield and yield* pages report a last modification date of July 8, 2025.

Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.