Generators and Iterators

The Symbol.iterator protocol that powers for...of and spread, and generator functions (function*) as the easiest way to implement it.

                function* gen() { yield value; } / obj[Symbol.iterator] = function* () {}
              

Purpose

An object is iterable if it implements Symbol.iterator, a well-known method returning an iterator — an object with a .next() method producing { value, done } pairs. This is what powers for...of and spread for any iterable, not just the built-in arrays/strings/Map/Set. A generator function (function*) is the easiest way to implement this protocol by hand.

Syntax

function range(start, end) {
  return {
    [Symbol.iterator]: function* () {
      for (let i = start; i < end; i++) {
        yield i;
      }
    },
  };
}

for (const n of range(1, 4)) {
  console.log(n); // 1, 2, 3
}

function* countUp() {
  yield 1;
  yield 2;
  yield 3;
}
const it = countUp();
it.next(); // { value: 1, done: false }
it.next(); // { value: 2, done: false }

Behavior notes

  • Calling a generator function does not run its body — it returns an iterator immediately. The body only advances, one yield at a time, as something pulls values from it.
  • A generator with an infinite loop containing a yield is a normal, useful pattern precisely because of this lazy behavior — nothing runs until a value is actually requested.
  • yield can also receive a value passed into .next(value), enabling two-way communication — rarely needed at this level, but the mechanism behind more advanced generator-based patterns.
  • for...of, spread, destructuring, and Promise.all (with an iterable of promises) all rely on the iterable protocol, not on the value specifically being an array.

Common mistakes

  • Expecting a generator function’s body to execute immediately upon calling it, the way a normal function does.
  • Trying to iterate a generator’s returned iterator a second time — once exhausted (done: true), it doesn’t reset; a fresh call to the generator function is needed for a new iteration.

Runtime notes

Generators and the iterable protocol are core ECMAScript (ES2015), identical across every current browser and Node version.

Taught in these lessons