By the end of this lesson, you will be able to identify JavaScript iterables, use for...of to walk through their values, and create a simple custom iterable.
What it is
An iterable is any value that can produce a sequence of items one at a time. In JavaScript, the built-in way to ask a value for that sequence is its Symbol.iterator method. When you write for...of, JavaScript calls that method to get an iterator, then repeatedly calls the iterator's next() method until it says it is done.
Related terms: iterator is the object returned by Symbol.iterator(); iterable is the object that has that method; for...of is the loop that consumes iterables. Common built-in iterables include arrays, strings, Map, Set, typed arrays, and generators.
Why it matters
- It gives you a uniform way to loop over many different data shapes.
- It lets you process values lazily, such as generators that produce items only when requested.
- It works with destructuring, such as
const [first, second] = iterable;. - It lets you spread iterables into arrays or function arguments, such as
[...mySet]. - It lets you make your own objects iterable, so they can be used with
for...of, spread, and destructuring.
Syntax or steps
The smallest useful pattern is:
for (const value of iterable) {
// use value
}
To make an object iterable, add a method keyed by Symbol.iterator. That method must return an object with a next() method. Each call to next() returns an object with value and done.
Example
const letters = "abc";
for (const ch of letters) {
console.log(ch);
}
const countdown = {
from: 3,
[Symbol.iterator]() {
let current = this.from;
return {
next() {
if (current > 0) {
return { value: current--, done: false };
}
return { value: undefined, done: true };
}
};
}
};
for (const n of countdown) {
console.log(n);
}
Part by part:
const letters = "abc";creates a string, which is iterable.for (const ch of letters)walks through each character:"a","b","c".const countdown = { ... }creates a plain object.[Symbol.iterator]()defines the method that makes the object iterable.let current = this.from;stores the starting number for this iteration.next()returns the next value and whether the sequence is finished.- The second loop prints
3,2,1.
Common mistakes
- Using
for...ofon a plain object without making it iterable. Plain objects are not iterable by default. Fix: useObject.keys(obj),Object.values(obj), or addSymbol.iterator. - Confusing
for...ofwithfor...in.for...ofgives values from an iterable;for...ingives property names from an object. Fix: choosefor...offor sequences andfor...inonly when you need keys. - Returning only
valuefromnext()withoutdone. The loop may not know when to stop. Fix: always return{ value, done }. - Forgetting that an iterator can be consumed once. If you need to loop again, create a new iterator. Fix: call
Symbol.iterator()again or use a fresh iterable.
When to use it
Use iterables when you care about the sequence of values. Use other loops when you care about indexes, keys, or side effects.
| Pattern | Best for | Example |
|---|---|---|
for...of | Walking through values of an iterable | for (const x of set) |
for...in | Enumerating object property names | for (const key in obj) |
forEach | Running a callback for each array element | arr.forEach(fn) |
Spread ... | Copying iterable values into an array or arguments | [...map.keys()] |
Practice
Guided exercise: create an iterable that yields the numbers 1, 2, and 3, then loop over it with for...of.
const oneTwoThree = {
[Symbol.iterator]() {
let n = 1;
return {
next() {
if (n <= 3) {
return { value: n++, done: false };
}
return { value: undefined, done: true };
}
};
}
};
for (const value of oneTwoThree) {
console.log(value);
}
Expected output: 1, 2, 3.
Challenge: make an iterable that yields the words "red", "green", and "blue". Hint: store the words in an array inside the object and return an iterator that walks through that array.
Quick check
Question: What method does for...of call to start walking through a value?
Answer: It calls the value's Symbol.iterator method to get an iterator.
Summary
Iterables are JavaScript values that can produce a sequence of items through Symbol.iterator. The for...of loop, spread syntax, and destructuring all rely on this same idea. Once you understand iterables, you can loop over built-in collections and make your own objects behave like sequences.