SKU // 79

JavaScript Iterables

An iterable is anything that can hand out its values one at a time, in order. Arrays, strings, Sets, and Maps are all iterables. That shared ability is why the same tools, for...of, spread ..., and Array.from, work on all of them.

// What Is Iterable?

Iterable Not iterable
ArrayPlain object { }
StringNumber
Set, MapWeakSet, WeakMap
Typed arrays, NodeListnull, undefined
const person = { name: "Ava", age: 16 };

for (const x of person) { }   // TypeError: person is not iterable
TypeError: person is not iterable

A plain object has no single obvious order for "its values," so JavaScript does not guess. You choose: Object.keys, Object.values, or Object.entries, each of which returns an iterable array.

Two entries in the table may be new. Typed arrays (like Uint8Array) are arrays that hold only one kind of number, used for things like image and sound data. A NodeList is the list of page elements you get back from document.querySelectorAll(), a web page feature outside this course. Both work with for...of.

// for...of on Each Iterable

Iterating means stepping through a sequence one element at a time. Here is for...of on each of the four main iterables. Watch what each one hands you:

for (const x of "Hey") console.log(x);                      // characters
for (const x of [2, 4]) console.log(x);                     // elements
for (const x of new Set(["a", "b"])) console.log(x);        // values

const fruits = new Map([["apples", 500], ["bananas", 300]]);
for (const x of fruits) console.log(x);                    // [key, value] pairs
H e y 2 4 a b ["apples", 500] ["bananas", 300]

A Map is the one that surprises people: each step gives a two-element array. Destructure it with for (const [fruit, qty] of fruits) to get the parts by name.

// Everything That Accepts an Iterable

Once something is iterable, all of these work on it:

const word = "code";

for (const ch of word) { }                // for...of
[...word]                                 // spread: ["c", "o", "d", "e"]
Array.from(word)                          // ["c", "o", "d", "e"]
new Set(word)                             // Set {"c", "o", "d", "e"}
const [first, second] = word;            // destructuring: "c", "o"
Math.max(...new Set([3, 9, 4]))           // 9
["c", "o", "d", "e"] ["c", "o", "d", "e"] Set(4) {"c", "o", "d", "e"} c o 9
Big Idea
These tools do not care what they are given, only that it can produce values one by one. Write code against "an iterable," and it works for arrays, strings, Sets, Maps, and anything else that follows the same rules.

// Strings Iterate by Character, Not by Code Unit

Some characters, like most emoji, take up two slots internally. Indexing and length see those two slots; iteration sees one real character:

const s = "hi😀";

console.log(s.length);        // 4   (the emoji counts as 2)
console.log([...s].length);   // 3   (h, i, 😀)
console.log(s[2]);            // "\ud83d"  half an emoji: garbage
console.log([...s][2]);       // "😀"
Tip
To count or reverse text that might contain emoji, spread it into an array first: [...text].length or [...text].reverse().join("").

// Getting Iterables from Collections

Arrays, Sets, and Maps can each give you three different iterables:

const colors = ["red", "green"];

[...colors.keys()]      // [0, 1]
[...colors.values()]    // ["red", "green"]
[...colors.entries()]   // [[0, "red"], [1, "green"]]

// How to Tell If Something Is Iterable

Every iterable has a special method stored under the key Symbol.iterator. That method is what for...of actually calls behind the scenes (the next lesson shows it in action):

function isIterable(x) {
  return x != null && typeof x[Symbol.iterator] === "function";
}

isIterable([1, 2])         // true
isIterable("text")         // true
isIterable(new Map())      // true
isIterable({ a: 1 })       // false
isIterable(42)             // false
true true true false false

// Quick Check

Which of these is not iterable?

  1. "hello"
  2. new Set([1, 2])
  3. { a: 1, b: 2 }
  4. new Map()
Show answer
C. Plain objects are not iterable: for...of on one throws TypeError: ... is not iterable. Use Object.entries(obj) to get an iterable array of its pairs.

What does this log?

const m = new Map([["x", 1]]);
for (const item of m) console.log(item);
Show answer
["x", 1]. Looping over a Map gives [key, value] pairs, not just the values.

Why does [..."hi😀"].length give 3 when "hi😀".length gives 4?

  1. Spread removes duplicate characters
  2. Iteration steps by whole characters; length counts the emoji's two internal slots
  3. Spread skips the last character
  4. length counts the quote marks
Show answer
B. Most emoji take two slots inside a string. Indexing and length see both slots; iterating (spread, for...of) gives the emoji as one character.

// Try It

  1. Click Open Playground and run it. Read the error, then fix the loop with Object.entries
  2. Destructure the first three letters of a word into three variables
  3. Compare .length and [...s].length for a string with two emoji
  4. Open the isIterable example with its Try it Yourself button and test six different values, predicting each result first
// Video Walkthroughs
Last updated: Oct 10, 2026, 1:42 AM ET