liveBook · Manning

Iterator

As explained in The Joy of JavaScript

An iterator object is an object that implements the iterator protocol by providing a next method that produces iteration results.

An iterator is an object whose `next()` method returns an iteration result: an object with `value` and `done` properties. An iterable provides a `Symbol.iterator` method that returns an iterator; the two protocols work together but are not the same. section 9.1 section 9.1.2

This protocol lets JavaScript consumers request values without depending on a collection’s internal structure.

  • A result with `done: false` supplies another value; `done: true` signals the end. Results that break the contract cause a `TypeError`. section 9.1.2
  • Custom objects can expose iteration through `Symbol.iterator`, enabling consumers such as `for...of` and the spread operator to use them. section 9.1.3
  • An iterator need not be iterable: a `next()` method alone supports direct requests, while adding `Symbol.iterator` enables `for...of`. section 9.1.3
Listing 9.1 Random-number generator using an iterator
function randomNumberIterator(size = 1) {
  
  function nextRandomInteger(min) {                              #1
    return function(max) {
      return Math.floor(Math.random() * (max - min)) + min;
    };
  }
 
  const numbers = Array(size)                                    #2
     .fill(1)
     .map(min => nextRandomInteger(min)(Number.MAX_SAFE_INTEGER));
 
  return {
    next() {
      if(numbers.length === 0) {
        return {done: true};                                     #3
      }
      return {value: numbers.shift(), done: false};              #4
    }
  };
}
 
let it = randomNumberIterator(3);
console.log(it.next().value);  // 1334873261721158             #5
console.log(it.next().value);  // 6969972402572387             #5
console.log(it.next().value);  // 3915714888608040             #5
console.log(it.next().done);   // true

A random-number iterator shows `next()` returning values until the sequence is exhausted. section 9.1.3

class Block {

 index = 0;
 constructor(index, previousHash, data = [], difficulty = 0) {
   this.index = index;
   this.previousHash = previousHash;
   this.data = data;
   this.nonce = 0;
   this.difficulty = difficulty;
   this.timestamp = Date.now();
   this.hash = this.calculateHash();
 }

 //...

 [Symbol.iterator]() {
   return this.data[Symbol.iterator]();
 }
}

A `Block` delegates iteration to its stored data, making its transactions available through the iterator protocol. section 9.1.3

How The Joy of JavaScript covers it

How deep it goes
Defines the `next()` result contract, explains malformed results, and demonstrates custom implementations.
Examples
Uses random-number sequences, blockchain blocks and transactions, and strings as iteration examples.
What you can do after
Build it from scratch by implementing `next()` results, then enable `for...of` with `Symbol.iterator`.
How it connects
Connects iterators to iterable objects, generators, streams, `for...of`, and the spread operator.

Also explained in

Compare how 15 books explain iterator →

Related concepts

This explainer was generated by Manning's knowledge graph from the text of The Joy of JavaScript. The section links point to the parts of the book it draws on.