J

JavaScript Handbook

Clean • Professional

Iterables in JavaScript

4 minute

Iterables in JavaScript

In JavaScript, iterables are objects that can be looped over — meaning you can access their elements one by one using constructs like for...of, the spread operator (...), or destructuring.

An iterable is any object that implements the Symbol.iterator method.

This method returns an iterator — an object that defines how to access values sequentially.

Common Built-in Iterables

JavaScript provides several built-in iterable types:

Iterable TypeExample
Array[10, 20, 30]
String"Hello"
Mapnew Map([["a", 1], ["b", 2]])
Setnew Set([1, 2, 3])
Typed Arraysnew Uint8Array([5, 10, 15])
Arguments ObjectFunction’s arguments are iterable
Generator ObjectsReturned from generator functions

How Iterables Work

An iterable must have a method with the key Symbol.iterator, which returns an iterator object.

An iterator must implement a next() method that returns an object with two properties:

  • value → The next value in the sequence
  • donetrue if iteration is complete, otherwise false

Example:

const myArray = [10, 20, 30];
const iterator = myArray[Symbol.iterator]();

console.log(iterator.next()); // { value: 10, done: false }
console.log(iterator.next()); // { value: 20, done: false }
console.log(iterator.next()); // { value: 30, done: false }
console.log(iterator.next()); // { value: undefined, done: true }

Using Iterables

Iterables provide a consistent way to loop over various data structures like arrays, strings, sets, and maps. By implementing the Iterable Protocol using Symbol.iterator, any object can define how it should be iterated, giving full control over its looping behavior.

a. for...of Loop

Iterates over iterable values directly:

const fruits = ["apple", "banana", "cherry"];
for (const fruit of fruits) {
  console.log(fruit);
}
// Output: apple, banana, cherry

b. Spread Operator (...)

Expands iterables into elements:

const arr = [1, 2, 3];
const newArr = [...arr, 4, 5];
console.log(newArr); // [1, 2, 3, 4, 5]

c. Destructuring

Extracts iterable values:

const [a, b, c] = "XYZ";
console.log(a, b, c); // X Y Z

d. Array.from()

Converts any iterable into an array:

const set = new Set([1, 2, 3]);
const arr = Array.from(set);
console.log(arr); // [1, 2, 3]

Custom Iterables

You can make your own iterable objects by defining the Symbol.iterator method.

Example: Custom Iterable

const range = {
  start: 1,
  end: 5,
  [Symbol.iterator]() {
    let current = this.start;
    const end = this.end;
    return {
      next() {
        if (current <= end) {
          return { value: current++, done: false };
        } else {
          return { done: true };
        }
      }
    };
  }
};

for (const num of range) {
  console.log(num);
}
// Output: 1 2 3 4 5

Iterables vs. Iterators

ConceptDescriptionExample
IterableHas a Symbol.iterator methodArray, Set, Map, String
IteratorHas a next() method that returns { value, done }Result of calling array[Symbol.iterator]()

So every iterable produces an iterator when Symbol.iterator is called.

Checking if an Object is Iterable

You can check if an object is iterable by testing for Symbol.iterator:

const obj = {};
console.log(typeof obj[Symbol.iterator]); // undefined (not iterable)

const arr = [];
console.log(typeof arr[Symbol.iterator]); // function (iterable)

When to Use Iterables

  • Looping over sequences (arrays, maps, sets, strings)
  • Using for...of for cleaner iteration
  • Creating custom data structures (like ranges or linked lists)
  • Integrating with Generators for lazy evaluation

Summary Table

FeatureDescriptionExample
Symbol.iteratorDefines an object as iterable[Symbol.iterator]() { ... }
for...ofLoops through iterable valuesfor (x of arr)
next()Returns { value, done } from iteratoriterator.next()
Spread (...)Expands iterable[...iterable]
DestructuringUnpacks values from iterable[a, b] = iterable
Array.from()Converts iterable → arrayArray.from(set)

Custom Iterable with Class

Example using classes and private fields:

class Car {
  #year;
  constructor(name, year) {
    this.name = name;
    this.#year = year;
  }
  getYear() {
    return this.#year;
  }
}

class CarRegistry {
  #cars = [new Car("Ford", 2014), new Car("Audi", 2019)];
  [Symbol.iterator]() {
    let index = 0;
    return {
      next: () => {
        if (index < this.#cars.length) {
          return { value: this.#cars[index++], done: false };
        }
        return { done: true };
      }
    };
  }
}

const registry = new CarRegistry();
for (const car of registry) {
  console.log(car.name); // Ford, Audi
}
console.log([...registry].map(car => car.name)); // ["Ford", "Audi"]

Real-world Example

Iterating over a Map:

const userRoles = new Map([
  ["Alice", "Admin"],
  ["Bob", "Editor"],
  ["Charlie", "Viewer"]
]);

for (const [user, role] of userRoles) {
  console.log(`${user}: ${role}`);
}
// Output:
// Alice: Admin
// Bob: Editor
// Charlie: Viewer

 

Article 0 of 0