CodeBlanks Logo Icon CodeBlanks

The iterable protocol

JavaScript course · Advanced · Lesson 43/100

Learn how an object becomes iterable with Symbol.iterator.

The iterable protocol

To make an object iterable, you define a [Symbol.iterator] method. This method returns an iterator; an object with a next() method. When JavaScript sees for...of, it first calls this method, then pulls values with next() each step.

This contract is the iterable protocol. Arrays, strings, Map and Set already have it. You can add it to your own objects so they work with for...of, spread (...) and destructuring.

The iterator factory

[Symbol.iterator] works like a factory: each call returns a fresh iterator. That way the same iterable can be traversed multiple times independently. Inside, you keep a state variable with let and advance one step on each next() call.

When the iterator is exhausted, it returns { value: undefined, done: true }. for...of stops there. The power of the factory pattern: each loop starts with its own state and is not affected by the previous loop.

Exercise Make the list iterable

Create an object called list with an items property holding a three-element array. Add a [Symbol.iterator] method to the object. It should return an iterator: start with let i = 0, and on each next() call return the next item as { value, done: false }; when the array ends return { value: undefined, done: true }. Then loop over the items with for...of and log each one with console.log.

Show example solution
const list = {
  items: ["apple", "pear", "cherry"],
  [Symbol.iterator]() {
    let i = 0;
    const items = this.items;
    return {
      next() {
        if (i < items.length) {
          return { value: items[i++], done: false };
        }
        return { value: undefined, done: true };
      }
    };
  }
};
for (const item of list) {
  console.log(item);
}

Test yourself

  1. Which method must you define to make an object iterable?

    • [Symbol.iterator]
    • [Symbol.iterator()]
    • iterator()
    • Symbol()
    Show answer

    [Symbol.iterator] — Correct. The [Symbol.iterator] method makes an object iterable.

  2. Add the iterable method

    const list = {
      items: ["a", "b"],
      ____() {
        let i = 0;
        const items = this.items;
        return {
          next() {
            return items.length > i
              ? { value: items[i++], done: false }
              : { value: undefined, done: true };
          }
        };
      }
    };
    Show answer
    const list = {
      items: ["a", "b"],
      [Symbol.iterator]() {
        let i = 0;
        const items = this.items;
        return {
          next() {
            return items.length > i
              ? { value: items[i++], done: false }
              : { value: undefined, done: true };
          }
        };
      }
    };
  3. Iterable protocol concepts

    Symbol.iterator
    Method that produces iterators
    iterable
    Object with Symbol.iterator
    iterator
    Object with a next() method
    factory
    Fresh iterator each call

All lessons in Advanced