JavaScript for impatient programmers
Please support this book: buy it or donate
(Ad, please don’t block.)

27 Synchronous iteration



27.1 What is synchronous iteration about?

Synchronous iteration is a protocol (interfaces plus rules for using them) that connects two groups of entities in JavaScript:

The iteration protocol connects these two groups via the interface Iterable: data sources deliver their contents sequentially “through it”; data consumers get their input via it.

Figure 18: Data consumers such as the for-of loop use the interface Iterable. Data sources such as Arrays implement that interface.
Figure 18: Data consumers such as the for-of loop use the interface Iterable. Data sources such as Arrays implement that interface.

Fig. 18 illustrates how iteration works: data consumers use the interface Iterable; data sources implement it.

  The JavaScript way of implementing interfaces

In JavaScript, an object implements an interface if it has all the methods that it describes. The interfaces mentioned in this chapter only exist in the ECMAScript specification.

Both sources and consumers of data profit from this arrangement:

27.2 Core iteration constructs: iterables and iterators

Two roles (described by interfaces) form the core of iteration (fig. 19):

Figure 19: Iteration has two main interfaces: Iterable and Iterator. The former has a method that returns the latter.
Figure 19: Iteration has two main interfaces: Iterable and Iterator. The former has a method that returns the latter.

These are type definitions (in TypeScript’s notation) for the interfaces of the iteration protocol:

interface Iterable<T> {
  [Symbol.iterator]() : Iterator<T>;
}

interface Iterator<T> {
  next() : IteratorResult<T>;
}

interface IteratorResult<T> {
  value: T;
  done: boolean;
}

The interfaces are used as follows:

27.3 Iterating manually

This is an example of using the iteration protocol:

const iterable = ['a', 'b'];

// The iterable is a factory for iterators:
const iterator = iterable[Symbol.iterator]();

// Call .next() until .done is true:
assert.deepEqual(
  iterator.next(), { value: 'a', done: false });
assert.deepEqual(
  iterator.next(), { value: 'b', done: false });
assert.deepEqual(
  iterator.next(), { value: undefined, done: true });

27.3.1 Iterating over an iterable via while

The following code demonstrates how to use a while loop to iterate over an iterable:

function logAll(iterable) {
  const iterator = iterable[Symbol.iterator]();
  while (true) {
    const {value, done} = iterator.next();
    if (done) break;
    console.log(value);
  }
}

logAll(['a', 'b']);
// Output:
// 'a'
// 'b'

  Exercise: Using sync iteration manually

exercises/sync-iteration-use/sync_iteration_manually_exrc.mjs

27.4 Iteration in practice

We have seen how to use the iteration protocol manually, and it is relatively cumbersome. But the protocol is not meant to be used directly – it is meant to be used via higher-level language constructs built on top of it. This section shows what that looks like.

27.4.1 Iterating over Arrays

JavaScript’s Arrays are iterable. That enables us to use the for-of loop:

const myArray = ['a', 'b', 'c'];

for (const x of myArray) {
  console.log(x);
}
// Output:
// 'a'
// 'b'
// 'c'

Destructuring via Array patterns (explained later) also uses iteration under the hood:

const [first, second] = myArray;
assert.equal(first, 'a');
assert.equal(second, 'b');

27.4.2 Iterating over Sets

JavaScript’s Set data structure is iterable. That means for-of works:

const mySet = new Set().add('a').add('b').add('c');

for (const x of mySet) {
  console.log(x);
}
// Output:
// 'a'
// 'b'
// 'c'

As does Array-destructuring:

const [first, second] = mySet;
assert.equal(first, 'a');
assert.equal(second, 'b');

27.5 Quick reference: synchronous iteration

27.5.1 Iterable data sources

The following built-in data sources are iterable:

To iterate over the properties of objects, you need helpers such as Object.keys() and Object.entries(). That is necessary because properties exist at a different level that is independent of the level of data structures.

27.5.2 Iterating constructs

The following constructs are based on iteration:

  Quiz

See quiz app.