Range Over Iterators in JavaScript

Starting with version 1.23, support for iterators has been added, allowing us to iterate over almost anything!

Let’s look at the List type again. Previously, a List would return a slice of all its elements via an AllElements method. We can improve it using iterators.

class List {
  constructor() {
    this.head = null;
    this.tail = null;
  }

  push(value) {
    const newNode = { value: value, next: null };

    if (this.tail) {
      this.tail.next = newNode;
      this.tail = newNode;
    } else {
      this.head = newNode;
      this.tail = newNode;
    }
  }

  *all() {
    let current = this.head;
    while (current) {
      yield current.value;
      current = current.next;
    }
  }
}

function* genFib() {
  let [a, b] = [1, 1];
  while (true) {
    yield a;
    [a, b] = [b, a + b];
  }
}

const lst = new List();
lst.push(10);
lst.push(13);
lst.push(23);

for (const value of lst.all()) {
  console.log(value);
}

const fib = genFib();
for (let value of fib) {
  if (value >= 10) break;
  console.log(value);
}

All returns an iterator, which in JavaScript can be implemented using generator functions.

The iterator function can yield every element we want to iterate over, and we can stop iteration using the break statement.

Iteration doesn’t require an underlying data structure and doesn’t even have to be finite! Here’s a generator function for Fibonacci numbers that keeps running as long as the break statement isn’t triggered.

function* genFib() {
  let [a, b] = [1, 1];
  while (true) {
    yield a;
    [a, b] = [b, a + b];
  }
}

const fib = genFib();
for (let value of fib) {
  if (value >= 10) break;
  console.log(value);
}

With the List implementation, you can now create a list, push values to it, and iterate over them using the for...of loop.

Since List.all returns an iterator, it can be used in a regular for...of loop.

const lst = new List();
lst.push(10);
lst.push(13);
lst.push(23);

for (const value of lst.all()) {
  console.log(value);
}

List all its values using the for...of loop. This collects all values from the all iterator.

const fib = genFib();
for (let value of fib) {
  if (value >= 10) break;
  console.log(value);
}

Next example: Errors.