JavaScript
Challenge - Custom iterable
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
-
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.
-
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;
}
}
-
Match the iterable concepts
- Symbol.iterator
- Iterable protocol
- function*
- Generator function
- yield
- Produces a value
- .next()
- Next value
Next lesson: Challenge - IndexedDB app