The Iterator Protocol

The Iterator Protocol is a standardized way to produce a sequence of values, one at a time, on demand. It allows objects to define their iteration behavior, such as what values are looped over in a for...of loop.

Illustration of The Iterator Protocol
Illustration of The Iterator Protocol

💡 Core Concept

An object is an iterator if it implements a next() method that returns an object with two properties: value and done.

Iterator Interface

  • next(): Returns an object { value, done }.
  • value: The next value in the sequence.
  • done: Boolean, true if iteration is complete, otherwise false.

📌 Deep Dive: Basic Iterator Object

JAVASCRIPT
const iterator = {
  current: 1,
  last: 3,
  next() {
    if (this.current <= this.last) {
      return { value: this.current++, done: false };
    } else {
      return { done: true };
    }
  }
};

console.log(iterator.next()); // { value: 1, done: false }
console.log(iterator.next()); // { value: 2, done: false }
console.log(iterator.next()); // { value: 3, done: false }
console.log(iterator.next()); // { done: true }
Output
{ value: 1, done: false }
{ value: 2, done: false }
{ value: 3, done: false }
{ done: true }

Iterable vs Iterator

An iterable is an object that implements the @@iterator method, accessible via Symbol.iterator, which returns an iterator.

The iterator is the object that actually produces the sequence via next().

Iterable vs Iterator
PropertyIterableIterator
Has Symbol.iteratorYesUsually no
Has next()NoYes
ReturnsIteratorSequence values
Used infor...of, spread operatorManual iteration

Making an Object Iterable

To make a custom object iterable (usable in for...of), implement the Symbol.iterator method that returns an iterator.

📌 Deep Dive: Custom Iterable Object

JAVASCRIPT
const iterable = {
  start: 1,
  end: 3,
  [Symbol.iterator]() {
    let current = this.start;
    let last = this.end;
    return {
      next() {
        if (current <= last) {
          return { value: current++, done: false };
        } else {
          return { done: true };
        }
      }
    };
  }
};

for (const num of iterable) {
  console.log(num);
}
// Output: 1 2 3
Output
1
2
3

💡 Built-in Iterables

Arrays, Strings, Maps, Sets, and many other built-in objects implement the iterator protocol internally.

Why Use the Iterator Protocol?

  • Enables for...of loops over custom data structures.
  • Allows lazy evaluation of values one at a time.
  • Supports interoperability between different data types.

⚠️ Important

Do not confuse the iterator protocol with the iterable protocol. The iterable protocol requires Symbol.iterator returning an iterator; the iterator protocol requires a next() method.