CodeBlanks Logo Icon CodeBlanks

Challenge - Custom iterable

JavaScript course · Advanced · Lesson 98/100

Build a custom iterable collection with Symbol.iterator and a generator.

Custom iterable

In this challenge you will write a Range class that walks numbers from start to end as a custom iterable. To make an object iterable you define the [Symbol.iterator] method.

That method returns an iterator — an object with a next() method that gives the next value on each call. The iterator protocol returns { value, done }.

The easiest way is to write this method as a generator: it starts with function* and produces values with yield.

Generators and yield

A generator function is declared with function*. Inside it, the yield keyword produces a value and pauses; the next next() call resumes from there.

function* count() {
  yield 1;
  yield 2;
}

To use a generator as a class method you put * before the method name: *[Symbol.iterator]() { ... yield ... }. This is far shorter than writing next() by hand.

Exercise Make the Range class iterable

Write a Range class whose constructor takes start and end and assigns them to this.start and this.end. Add a *[Symbol.iterator]() generator method that uses a for loop to yield each number from this.start to this.end.

Show example solution
Write class Range { constructor(start, end) { this.start = start; this.end = end; } *[Symbol.iterator]() { for (let n = this.start; n <= this.end; n++) { yield n; } } }.

Example solution:
class Range {
  constructor(start, end) {
    this.start = start;
    this.end = end;
  }
  *[Symbol.iterator]() {
    for (let n = this.start; n <= this.end; n++) {
      yield n;
    }
  }
}

Test yourself

  1. Which method makes an object iterable?

    class Range {
      *[Symbol.iterator]() {
        yield 1;
      }
    }
    • Symbol.iterator
    • Symbol.generator
    • Symbol.iterable
    • Symbol.next
    Show answer

    Symbol.iterator — Correct! The [Symbol.iterator] method provides the iterable protocol.

  2. Add the generator iterator method

    class Range {
      constructor(start, end) {
        this.start = start;
        this.end = end;
      }
      ____
        yield this.start;
        yield this.end;
      }
    }
    Show answer
    class Range {
      constructor(start, end) {
        this.start = start;
        this.end = end;
      }
      *[Symbol.iterator]() {
        yield this.start;
        yield this.end;
      }
    }
  3. Match the iterable concepts

    Symbol.iterator
    Iterable protocol
    function*
    Generator function
    yield
    Produces a value
    .next()
    Next value

All lessons in Advanced