Pebellslearn by building
0%
RoadmapsMatrixCoursesSandboxSign in
Iterators and Generators  ›  Lesson

Iterables and the Iterator Protocol

Iterables and Iterator Protocol 12 minAn iterable has a Symbol.iterator method that returns an iterator object; the iterator's next() returns { value, done }, and for...of and the spread operator both repeat this call automatically until done is true.

Iterables and the Iterator Protocol

In short: for...of, the spread operator ([...x]), and destructuring all work through one shared mechanism: an iterable is any value with a [Symbol.iterator] method, which returns an iterator — an object with a next() method. Calling next() returns { value, done }: the current item, and whether there are more to come. for...of calls next() repeatedly for you, stopping the instant done is true. Arrays, strings, Maps and Sets all come with this built in; a plain object does not, unless you add it yourself.

A conveyor with two items and a next() lever: it.next() pulls one item and moves the belt forward, returning { value: "Blue Hour", done: false }; once the belt is empty, next() gives { value: undefined, done: true } and a "done" light — for...of and [...x] call next() for you, stopping the moment done is true

Pull items from an array's iterator by hand

Every array already has a [Symbol.iterator] method; calling it directly shows exactly what for...of does under the hood:

javascript

The first two calls return { value: "Blue Hour", done: false } and { value: "Red Dawn", done: false }. The third, with nothing left, returns { value: undefined, done: true } — this is the exact signal for...of watches for to know when to stop.

Make a plain object iterable

A plain object has no built-in [Symbol.iterator] — add one, returning an object with its own next(), and for...of and the spread operator both start working on it:

javascript

for...of calls playlist[Symbol.iterator]() once to get the iterator, then next() repeatedly, printing each song and stopping cleanly once done is true. [...playlist] uses that exact same protocol to build a real array, ["Blue Hour", "Red Dawn", "Green Tide"].

The trap: assuming every object works in for...of

Without a [Symbol.iterator] method, for...of doesn't loop zero times or skip silently — it throws immediately, before the loop body ever runs:

javascript

This throws TypeError: plain is not iterable. Plain objects are deliberately not iterable by default — for their key/value pairs, use for...in, or Object.entries(plain) (which returns a real, iterable array) inside a for...of.

Quick practice

quick drill

What does arr[Symbol.iterator]().next() return for a non-empty array's first call?

quick drill

What does an iterator's next() return once there's nothing left to give?

quick drill

What method must an object have to be usable in for...of?

quick drill

What happens when you use for...of on a plain object with no [Symbol.iterator]?

quick drill

What does [...playlist] do, given playlist has a working [Symbol.iterator]?

🎯 Your turn

A plain object const playlist = { songs: ["a", "b"] }; throws TypeError: playlist is not iterable when used in for (const s of playlist) {}. Explain exactly why, and what you would add to playlist to fix it, in terms of Symbol.iterator, next(), value and done.

Write your explanation and submit it — there's no code to run here, just your reasoning.

Practice — level up

0/1 solved

Write your answer, then compare it with a rubric and a model answer.

ExplainMake an object work in for...of

A plain object const playlist = { songs: ["a", "b"] }; throws TypeError: playlist is not iterable when used in for (const s of playlist) {}. Explain exactly why, and what you would add to playlist to fix it, in terms of Symbol.iterator, next(), value and done.