Skip to main content

JavaScript Generators & Iterators

JavaScript Generator Functions

Written by Published

A generator function can pause with yield and resume later, producing one value at a time.

Writing an iterator by hand, as in the first lesson, is fiddly to get right.

A generator writes the same thing as an ordinary-looking function.

Example

Example

javascript

function* countTo(max) {
  for (let i = 1; i <= max; i++) {
    yield i;
  }
}

const counter = countTo(3);

console.log(counter.next());
console.log(counter.next());

Calling a generator function does not run it; it returns an iterator.

function* and yield

The * after function marks it as a generator.

yield pauses execution and hands out a value.

Calling next() resumes it from exactly where it paused.

Syntax

Syntax

javascript

function* name() {
  yield value;
}

Calling the generator function returns an iterator, not a result.

Nothing Runs Until next Is Called

The body does not start executing when the function is called.

Example

Example

javascript

const order = [];

function* demo() {
  order.push("started");
  yield 1;
}

const g = demo();
order.push("called, not started yet");
g.next();

console.log(order.join(" | "));

The output is called, not started yet | started.

Using for of on a Generator

A generator's return value is iterable, so it works directly in a loop.

Example

Example

javascript

function* countTo(max) {
  for (let i = 1; i <= max; i++) {
    yield i;
  }
}

const values = [];
for (const n of countTo(3)) {
  values.push(n);
}

console.log(values.join(","));

No manual next() calls were needed.

The Final done Value

A return inside a generator sets the last value and ends it.

Example

Example

javascript

function* demo() {
  yield 1;
  yield 2;
  return "finished";
}

const g = demo();

console.log(g.next());
console.log(g.next());
console.log(g.next());

The last call has done: true and carries the returned value.

Spreading a Generator

Because it is iterable, spread collects every yielded value.

Example

Example

javascript

function* countTo(max) {
  for (let i = 1; i <= max; i++) {
    yield i;
  }
}

const values = [...countTo(4)];

console.log(values.join(","));

The output is 1,2,3,4.

Delegating with yield*

One generator can hand off to another entirely.

Example

Example

javascript

function* inner() {
  yield "a";
  yield "b";
}

function* outer() {
  yield 1;
  yield* inner();
  yield 2;
}

console.log([...outer()].join(","));

The output is 1,a,b,2.

Complete Example

Complete Example

html

<!DOCTYPE html>
<html>
<head>
  <title>JavaScript Generator Functions</title>
</head>
<body>

  <h1>Generator Functions</h1>

  <p id="out"></p>

  <script>
    function* countTo(max) {
      for (let i = 1; i <= max; i++) {
        yield i;
      }
    }

    const values = [];
    for (const n of countTo(5)) {
      values.push(n);
    }

    document.getElementById("out").textContent = values.join(", ");
  </script>

</body>
</html>

Try It Yourself

Run the above example in the Try It Editor.

Try a bigger range:

Change 5 to 10 and see the list grow.

Important Points

  • function* declares a generator.
  • yield pauses and hands out a value.
  • Calling a generator function returns an iterator without running the body.
  • A generator works directly with for of and spread.
  • yield* delegates to another generator.

Conclusion

Generators are the practical way to build an iterator.

They read like an ordinary loop, but pause instead of running to completion.

The next lesson covers passing values back in as it runs.