JavaScript
Summary - Iterators
Build a number-range iterable object using Symbol.iterator.
Summary - Iterators
In this group you learned the iterator protocol, the iterable protocol and how to write a custom iterator. An iterator returns { value, done } from next(). An object becomes iterable when you add [Symbol.iterator]; it then works with for...of, spread and destructuring.
When writing a custom iterator you keep state with let and keep it alive in next() via closure. Every [Symbol.iterator] call produces a fresh iterator; so the same iterable can be traversed independently multiple times.
Tips and common pitfalls
Once an iterator is exhausted, calling next() again keeps returning { value: undefined, done: true }; no error is thrown. To start a new loop, use the iterable, not the iterator; iterators are one-shot.
Do not mix up for...in and for...of: the former walks object keys, the latter walks values. Also null and undefined are not iterable; for...of throws on them.
Exercise Stepped number range
Write a function called makeRange(start, end, step). The function should return an iterable object: its [Symbol.iterator] method starts with let current = start and returns an iterator. The iterator's next() method returns { value, done: false } while current <= end, advancing current by step each step; otherwise it returns { value: undefined, done: true }. Then create a range with makeRange(1, 10, 2), log the numbers with for...of, and spread it into an array with [...range] to log its length.
Show example solution
function makeRange(start, end, step) {
return {
[Symbol.iterator]() {
let current = start;
return {
next() {
if (current <= end) {
const value = current;
current += step;
return { value, done: false };
}
return { value: undefined, done: true };
}
};
}
};
}
const range = makeRange(1, 10, 2);
for (const num of range) {
console.log(num);
}
const arr = [...range];
console.log(arr.length);
Test yourself
-
What must you add to make an object iterable?
- A toString method
- A [Symbol.iterator] method
- A length property
- A valueOf method
Show answer
A [Symbol.iterator] method — Correct. Adding [Symbol.iterator] makes the object iterable.
-
Make makeRange iterable
function makeRange(start, end, step) {
return {
____() {
let current = start;
return {
next() {
if (end >= current) {
const value = current;
current += step;
return { value, done: false };
}
return { value: undefined, done: true };
}
};
}
};
}
Show answer
function makeRange(start, end, step) {
return {
[Symbol.iterator]() {
let current = start;
return {
next() {
if (end >= current) {
const value = current;
current += step;
return { value, done: false };
}
return { value: undefined, done: true };
}
};
}
};
}
Next lesson: Generator functions