Codectionary / Developer documentation / JavaScript

Iterables and Generators

An iterable is any object that implements the Symbol.iterator method, allowing it to be used with for...of and the spread operator - arrays, strings, Maps, and Sets are all built-in iterables. Generator functions, defined with function*, provide an easy way to create custom iterables by using yield to produce a sequence of values one at a time, pausing execution between each.

Syntax

function* generatorName() {
  yield value;
}

Examples

Basic Generator Function

A generator that produces values lazily, one at a time.

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

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

Using Generators with for...of

Generators are iterable, so they work directly with for...of and spread.

function* fruits() {
  yield "apple";
  yield "banana";
  yield "cherry";
}

for (const fruit of fruits()) {
  console.log(fruit);
}
// apple, banana, cherry

console.log([...fruits()]); // ["apple", "banana", "cherry"]

Custom Iterable Object

Making any object work with for...of by implementing Symbol.iterator.

const range = {
  from: 1,
  to: 5,
  [Symbol.iterator]() {
    let current = this.from;
    const last = this.to;
    return {
      next() {
        if (current <= last) {
          return { value: current++, done: false };
        }
        return { value: undefined, done: true };
      }
    };
  }
};

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

Best practices

  • Use generators for lazily-computed sequences, especially large or potentially infinite ones, since values are only produced as they are requested
  • Prefer generators over manually managing iterator state objects - the syntax is far more readable
  • Remember a generator function returns an iterator when called - it does not run its body immediately
  • Reach for this pattern when building custom data structures (like a tree or linked list) that should support for...of

At a glance

Purpose
Application logic and interaction
File extension
.js ยท .mjs
Runs in
Browsers and JavaScript runtimes
Usually used with
HTML, CSS and Web APIs

Specifications & further reading

Related JavaScript documentation