JS Iterators Protocol
In this page:
What Is an Iterator?
An iterator is an object that provides values one at a time. It has a next() method. Arrays, Maps, Sets, and strings are all built-in iterables, which is what lets for...of and the spread operator work uniformly across such different data structures.
Example: What Is an Iterator?
const arr = [1, 2, 3];
const iterator = arr[Symbol.iterator]();
console.log(iterator.next());
next() Result
The next() method returns an object with value and done properties. done becomes true when iteration ends. Once done is true, further calls to next() should keep returning { value: undefined, done: true } rather than throwing or restarting the sequence.
Example: next() Result
const arr = ["a"];
const it = arr[Symbol.iterator]();
console.log(it.next()); // { value: "a", done: false }
console.log(it.next()); // { value: undefined, done: true }
Iterable Protocol
An iterable object provides a Symbol.iterator method. Arrays, strings, and maps are common iterables. This shared protocol is what lets for...of, spread syntax, and destructuring all work on any object that implements it, not just the language's own built-in collections.
Example: Iterable Protocol
const iterable = {
[Symbol.iterator]() {
let i = 0;
return { next: () => i < 3 ? { value: i++, done: false } : { value: undefined, done: true } };
},
};
for (const v of iterable) console.log(v);
Custom Iterator
You can create your own iterator by defining a next() method and returning value and done. This is the underlying mechanism generators use automatically — writing function* gives you an iterator without manually managing the next()/done bookkeeping yourself.
Example: Custom Iterator
function makeIterator(max) {
let i = 0;
return { next: () => i < max ? { value: i++, done: false } : { value: undefined, done: true } };
}
const it = makeIterator(2);
console.log(it.next(), it.next(), it.next());
Iterator vs Iterable
An iterator has next(). An iterable has Symbol.iterator that returns an iterator. Some objects can be both. Knowing this distinction helps when building custom data structures: implement Symbol.iterator (making it iterable) rather than manually exposing a next() method on the object itself.
Example: Iterator vs Iterable
function* gen() { yield 1; }
const g = gen();
console.log(typeof g.next); // iterator: has next()
console.log(typeof g[Symbol.iterator]); // iterable: has Symbol.iterator too
Chapter Quiz — Complete all 8 topics to unlock
0/8 topics done
Complete these topics first: