Stop 04 · JavaScriptTopics · 36/36

Iterators

Part of the Frontend Developer Roadmap

In short

for...of works on arrays, strings, Maps and Sets, but not on plain objects. The reason is the iterator protocol, and once you get it you can make your own things loopable.

Objects that implement the iterator protocol (`.next()` returning `{value, done}`), the underlying mechanism that makes `for...of` and spread syntax work on arrays, strings, Maps and Sets. The iterator protocol provides a common abstraction for sequential consumption, which is why many built-in collections work with `for...of`, spread, and destructuring.

The jaadu mascot presses the button on a clinic token machine as a token slides out.

Think of it like this

The clinic token machine

At a clinic, you press the button and get the next token number. At closing time it shows "no more tokens". You never see the whole list, you just keep asking "next?". An iterator is that machine: next() hands over one value until done is true.

Watch it happen

What for...of asks clinicQueue

for...of
clinicQueue
iterator

[Symbol.iterator]()

1/7for...of first asks the object for an iterator.

The big ideas

What you need to know

Iterator: has next()

An iterator is any object with a next() method that returns { value, done }.

Iterable: has Symbol.iterator

An iterable is an object with a [Symbol.iterator]() method that returns a fresh iterator.

Built-ins are iterable

Arrays, strings, Maps, Sets and NodeLists all are. Plain objects aren't, so use Object.entries(obj).

Lots of syntax uses it

for...of, spread, array destructuring and Array.from all ask for an iterator behind the scenes.

See it in code

Walk through the code

js
1const clinicQueue = {2  patients: ["Asha", "Vikram", "Zoya"],3  [Symbol.iterator]() {4    let i = 0;5    return {6      next: () =>7        i < this.patients.length8          ? { value: this.patients[i++], done: false }9          : { value: undefined, done: true },10    };11  },12};13 14for (const p of clinicQueue) console.log(p);  // Asha, Vikram, Zoya15console.log([...clinicQueue].length);          // 3

1/4A plain object holding a list of patients.

next is an arrow function, so this still points to clinicQueue. Each for...of or spread calls [Symbol.iterator]() again and starts from 0.

Save yourself the pain

Common mistakes

Oops

Writing for (const x of someObject) on a plain object.

Do this instead

You'll get "someObject is not iterable". Loop over Object.entries(someObject) or Object.keys(someObject) instead.

Oops

Reusing an iterator after it's finished and expecting it to start over.

Do this instead

An iterator is used up once done is true. Get a new one from the iterable.

Your mission

Make a range

~20 min

Quick check

What happens? for (const x of { a: 1 }) console.log(x);

Go deeper

  1. 1Manually call `.next()` on an array's iterator (`arr[Symbol.iterator]()`). Validate your understanding by applying it in a small practical example.
  2. 2Implement a custom iterable object using `Symbol.iterator`. Validate your understanding by applying it in a small practical example.
  3. 3Understand how generators are a convenient shortcut for writing iterators.

More topics at this stop

Stuck on this topic? Ask an Insider

Get 1:1 guidance from people who've walked this exact path — on the InsideEdge app.

Download
InsideEdge