An iterator is any object with a next() method that returns { value, done }. An iterable is anything that can produce such an iterator—usually via [Symbol.iterator](). Built-in loops and spread syntax depend on that contract.
What is an iterator?
From Latin iterare (“to repeat”), an iterator lets you visit each item in a sequence without loading the whole collection into memory at once.
Common ways to walk data in JavaScript:
forloops over indices or keys- Array methods such as
mapandfilter(they still materialize or scan collections) - Iterators and
for..of, which consume values lazily through a shared protocol
Why iterators?
You already know loops and array methods. Iterators still matter because:
for..ofandfor await..ofcall into the iterator protocol under the hood.- An iterator can pause between values; the consumer decides when to call
next()again. - Sequences can be unbounded or expensive to copy into an array; iterators produce values on demand.
Iterator protocol
Technically, an iterator is any object whose next() method returns a result object with:
value— the current item (oftenundefinedwhendoneis true)done—truewhen the sequence is finished
Calling next() is often called consuming the iterator; many iterators are single-pass (you cannot rewind without creating a new iterator).
What is an iterable?
An iterable is a value you can iterate over with for..of or spread. It must provide a [Symbol.iterator]() method that returns a fresh iterator.
Built-in iterables include Array, String, Map, Set, TypedArray, and arguments (in non-arrow functions).
Create a custom iterable
const myIterable = { *[Symbol.iterator]() { yield 1; yield 2; yield 3; },};
for (const value of myIterable) { console.log(value);}// 1, 2, 3
console.log([...myIterable]); // [1, 2, 3]for..of walks values on iterables. for..in walks enumerable string keys on objects—a different loop for a different job.
Iterating over an array
With for..of:
const arr = [1, 2, 3, 4];
for (const value of arr) { console.log(value);}Or via the array’s iterator:
const arr = [1, 2, 3, 4];const it = arr[Symbol.iterator]();
console.log(it.next()); // { value: 1, done: false }console.log(it.next()); // { value: 2, done: false }console.log(it.next()); // { value: 3, done: false }console.log(it.next()); // { value: 4, done: false }console.log(it.next()); // { value: undefined, done: true }Iterating over a Map
With for..of (default entries are [key, value] pairs):
const map = new Map([ ["key1", "value 1"], ["key2", "value 2"],]);
for (const [key, value] of map) { console.log(`${key} and ${value}`);}Using the map iterator directly:
const mapIterator = map[Symbol.iterator]();
console.log(mapIterator.next()); // { value: ["key1", "value 1"], done: false }console.log(mapIterator.next()); // { value: ["key2", "value 2"], done: false }console.log(mapIterator.next()); // { value: undefined, done: true }Iterating over a Set
const set = new Set(["Apples", "Bananas"]);
for (const value of set) { console.log(value);}const setIterator = set[Symbol.iterator]();
console.log(setIterator.next()); // { value: "Apples", done: false }console.log(setIterator.next()); // { value: "Bananas", done: false }console.log(setIterator.next()); // { value: undefined, done: true }Create a custom iterator
Manual next()
You can implement next() by hand. It works, but callers cannot tell from the type alone that your object is an iterator—prefer exposing iterables (with [Symbol.iterator]) or generator functions.
function myIterator(start, finish) { let index = start;
return { next() { if (index < finish) { return { value: index++, done: false }; } return { value: undefined, done: true }; }, };}
const it = myIterator(0, 8);let res = it.next();while (!res.done) { console.log(res.value); res = it.next();}// 0 … 7Relation to generators
Hand-rolled iterators must track state yourself. Generator functions (function*) are the usual way to build iterators: they return an iterator object and use yield for each step. That is the focus of the next chapter.
Continue with Generators in JavaScript.