Code Reference

Iterators & Generators

JavaScript · Reference cheat sheet

Iterators & Generators

JavaScript · Reference cheat sheet

📋 Overview

The iterable protocol (obj[Symbol.iterator]) supplies an iterator with next()\{ value, done \}. Generators (function*) produce iterators lazily and support yield / yield*. Async generators use async function* and for await...of.

🔧 Core concepts

  • Iterable: has [Symbol.iterator]() returning an iterator.
  • Iterator: \{ next() \}; optional return() / throw().
  • Generator: function* pauses at yield; calling it returns a generator object.
  • yield*: delegate to another iterable/generator.
  • Async: async function*, yield awaited values, consume with for await.
const iterable = {
  *[Symbol.iterator]() {
    yield 1;
    yield 2;
  },
};
[...iterable]; // [1, 2]

💡 Examples

function* range(start, end, step = 1) {
  for (let i = start; i < end; i += step) yield i;
}
console.log([...range(0, 5)]); // [0,1,2,3,4]

function* idGen() {
  let id = 1;
  while (true) yield id++;
}
const ids = idGen();
ids.next().value; // 1

// yield*
function* flatten(arr) {
  for (const x of arr) {
    if (Array.isArray(x)) yield* flatten(x);
    else yield x;
  }
}
[...flatten([1, [2, [3], 4]])]; // [1,2,3,4]

// Manual iterator
const it = range(0, 2);
console.log(it.next()); // { value: 0, done: false }
console.log(it.next());
console.log(it.next()); // { value: undefined, done: true }

// Async generator
async function* poll(url, signal) {
  while (!signal.aborted) {
    const data = await fetch(url, { signal }).then((r) => r.json());
    yield data;
    await new Promise((r) => setTimeout(r, 1000));
  }
}
// Infinite take helper
function take(n, iterable) {
  return {
    *[Symbol.iterator]() {
      let i = 0;
      for (const v of iterable) {
        if (i++ >= n) return;
        yield v;
      }
    },
  };
}
[...take(3, idGen())]; // [1,2,3]

⚠️ Pitfalls

  • Generators are lazy — side effects run only as you pull values.
  • After done: true, further next() stay done (unless still open with return values).
  • break in for...of calls iterator return() — use try/finally in generators for cleanup.
  • Do not mix sync for...of with async generators — use for await...of.
  • Spreading infinite generators never finishes.

On this page