ReviseAlgo Logo

Arrays & Iterables

Iterators & the Iterable Protocol

Master JavaScript iteration protocols. Learn how objects implement Symbol.iterator, how the next() method resolves, and how to write custom iterables.

Last Updated: July 15, 2026 12 min read

1. Introduction

ES6 introduced iteration protocols to standardize how objects are iterated. The Iterable Protocol defines how objects expose iteration behavior to loops, while the Iterator Protocol defines how elements are retrieved sequentially.

2. Why It Matters

Many built-in features (like for...of loops, the spread operator, destructuring, and Array.from) rely on these protocols under the hood. Implementing them lets you make custom objects iterable.

3. Real-World Analogy

Think of a Turnstile Ticket Gate:

  • Iterable Protocol (Having a Card Reader slot): The gate exposes a standard ticket slot (the [Symbol.iterator] method). It signals that if you insert a valid card, it will start a passenger validation sequence.
  • Iterator Protocol (The Validation Sequence): The validation scanner inside. Each time a passenger walks forward, the gate scans the card, lets one person through, and returns status: "Passenger passed, more passengers waiting" ({ value: Passenger, done: false }). When the group is finished, it returns: "No passengers left" ({ done: true }).

4. The Protocols

To be compatible with built-in iteration features, an object must implement both protocols:

1. The Iterable Protocol:

The object must have a method with the key [Symbol.iterator]. This method must return an iterator object.

2. The Iterator Protocol:

The iterator object must implement a next() method. This method must return an object with two properties:
value: The current iteration value (can be omitted if done is true).
done: A boolean flag (true if iteration is finished, false otherwise).

5. Practical Example

Here is a custom range iterator that generates numbers between start and end:

6. Common Mistakes

  • Forgetting to return the iterator object from [Symbol.iterator]: The [Symbol.iterator] method must return an object containing a next function, otherwise the engine throws a TypeError when starting a loop.
  • Infinite loops: Forgetting to set done: true inside the next() return object causes loops to run indefinitely, crashing the execution context.

7. Quick Quiz

Q1: What symbol key is used to define an object's default iterator method?

A) Symbol.iterator

B) Symbol.iterable

Answer: A — The Symbol.iterator property specifies the default iterator function for an object.

8. Scenario-Based Challenge

The Custom Object Iterator:

You write a custom playlist manager containing nested song objects. To allow developers to run for (const song of playlist) directly, implement the [Symbol.iterator] method on the playlist class.

9. Debugging Exercise

Explain why this custom object iterator crashes during loop evaluation:

const userGroup = {
  users: ['Alice', 'Bob'],
  [Symbol.iterator]() {
    return {
      next() {
        // missing index state variable tracking!
        return { value: this.users[0], done: false }; 
      }
    };
  }
};

for (const name of userGroup) { console.log(name); } // infinite loop!

View Solution

Diagnosis: The iterator lacks state variables to track the current index position, and never sets done: true. This causes the loop to run indefinitely, returning the first element repeatedly.

Fix: Declare an index tracking variable inside the [Symbol.iterator] closure, and set done: true when the index reaches the array length:

const userGroup = {
  users: ['Alice', 'Bob'],
  [Symbol.iterator]() {
    let index = 0;
    return {
      next: () => {
        if (index < this.users.length) {
          return { value: this.users[index++], done: false };
        }
        return { done: true };
      }
    };
  }
};

10. Interview Questions

🟢 Q1: Describe the structure of the object returned by the iterator's next() method.

Answer: The next() method must return an object with two properties:
value: Represents the current element in the iteration. (Can be any data type, and is omitted when done is true).
done: A boolean flag. It is false if there are more elements to iterate, and true if the iteration is complete.

11. Production Considerations

  • Generators over Iterators: Writing custom iterators manually requires managing state variables (like index offsets) manually. In production, use Generators (which automatically implement the iteration protocols) to write custom iterables cleanly.