An object is iterable if it defines an iteration protocol via the [Symbol.iterator] property. Calling this method returns an iterator object with a .next() method returning { value, done }.
flowchart LR
Iterable["Iterable Object (e.g. Array)"] -->|Symbol.iterator()| Iterator["Iterator Instance"]
Iterator --> Next1["next() -> { value: 'A', done: false }"]
Next1 --> Next2["next() -> { value: 'B', done: false }"]
Next2 --> Next3["next() -> { value: undefined, done: true }"]
| Concept | Required Interface | Description |
|---|---|---|
| Iterable Protocol | [Symbol.iterator](): Iterator |
Object property that returns an iterator instance. |
| Iterator Protocol | next(): { value: any, done: boolean } |
Object method that retrieves sequential items until done: true. |
| Built-in Iterables | Arrays, Strings, Maps, Sets, TypedArrays, NodeLists | Built-in structures compatible with for...of and spread [...]. |
// Demonstrating custom iterable protocol implementation
// Custom Range Object implementing [Symbol.iterator]
const customRange = {
from: 1,
to: 3,
[Symbol.iterator]() {
let current = this.from;
const last = this.to;
// Return Iterator Object implementing next()
return {
next() {
if (current <= last) {
return { value: current++, done: false };
} else {
return { value: undefined, done: true };
}
}
};
}
};
// 1. Consuming custom iterable with for...of loop
console.log("--- Consuming Custom Iterable via for...of ---");
for (const num of customRange) {
console.log(`Range Value: ${num}`);
}
// 2. Consuming custom iterable with Spread Operator
const rangeArray = [...customRange];
console.log("Spread Custom Range into Array:", rangeArray); // [1, 2, 3]
// 3. Generator Function (Shorthand for creating iterables)
function* countdownGenerator(start) {
while (start > 0) {
yield start--;
}
}
console.log("--- Consuming Generator Iterator ---");
const countdown = countdownGenerator(3);
console.log(countdown.next()); // { value: 3, done: false }
console.log(countdown.next()); // { value: 2, done: false }
console.log(countdown.next()); // { value: 1, done: false }
console.log(countdown.next()); // { value: undefined, done: true }
function*): Writing custom iterators manually with [Symbol.iterator] requires state tracking boilerplate. Use generator functions (yield) to build clean iterators effortlessly.[...iterable] relies directly on the Symbol.iterator protocol.{ done: true }, it cannot be reset; create a new iterator instance by re-calling Symbol.iterator().Write a generator function evenGenerator(limit) using yield that yields all even numbers up to limit.
Sign in to track your learning journey, earn industry-recognized certificates, and join our elite developer community.
Quick Access With
Experiment with the code from this lesson in our interactive playground.
You've completed this section! Take a quick 5-question quiz to check your understanding.