W3docs

JavaScript Iterables and Iterators

In the vast and dynamic landscape of JavaScript programming, understanding iterables is pivotal. Iterables are a foundational concept, essential for efficiently

Introduction to JavaScript Iterables

JavaScript iterables are objects that implement a specific protocol, allowing them to be consumed by iteration constructs like for...of. This guide covers the core concepts, built-in iterables, and practical techniques for working with collections.

What are Iterables in JavaScript?

At its core, an iterable is an object that implements the Symbol.iterator method, enabling sequential access to its elements. Several built-in types in JavaScript are iterable, including Array, String, Map, Set, and more. It is important to distinguish between an iterable (the object being traversed) and an iterator (the object returned by Symbol.iterator that actually performs the traversal). These iterables are integral to various operations, such as looping and data manipulation.

Info

For a detailed exploration of JavaScript Map and Set objects, please refer to our comprehensive guide on JavaScript Map and Set.

Example of an Iterable: Array

Let's look at a basic example of an iterable in JavaScript:

javascript— editable

This code snippet demonstrates iterating over an array of fruits, a common iterable. The for...of loop automatically calls the iterable's Symbol.iterator method and consumes the resulting iterator until done is true. See JavaScript loops for the full family of looping constructs.

Warning

Do not confuse for...of with for...in. for...of iterates over the values produced by an iterable (array items, string characters, Map entries). for...in iterates over the enumerable property keys of an object — including inherited ones — and is meant for plain objects, not arrays. Using for...in on an array gives you index strings ("0", "1", …) and can pick up extra properties, so prefer for...of for ordered data.

The Iterator Protocol

The cornerstone of an iterable is its Symbol.iterator method. The protocol is a precise contract:

  1. An iterable has a method keyed by Symbol.iterator. Calling it returns an iterator.
  2. An iterator is an object with a next() method.
  3. Each call to next() returns an object { value, done }:
    • done: falsevalue is the next item in the sequence.
    • done: true — iteration is finished (value is then ignored, or carries an optional final result).

Any object that follows this contract works with for...of, the spread operator, destructuring, and Array.from() — even if you wrote the object yourself. Symbol is a built-in unique key; see Symbol type for why these protocol methods use one instead of a plain string name.

Example: A custom range iterable

A classic use case is an object that produces a numeric range lazily, without ever building an array:

javascript— editable

In this example, the [Symbol.iterator]() method returns a fresh iterator each time, so the same range object can be looped over more than once. The method shorthand syntax ensures this correctly refers to the range object. (Using an arrow function for [Symbol.iterator] would capture this lexically and break the pattern.)

Generators: the easy way to build iterables

Writing next() and tracking state by hand is verbose. A generator function — declared with function* and using yield — produces an iterator automatically. Each yield pauses the function and hands a value to the consumer; execution resumes on the next next() call. The same range becomes far shorter:

javascript— editable

The * before the method name makes it a generator method, so range is iterable with almost no boilerplate. For everything generators can do — including two-way communication and delegation with yield* — see Generators and Async iterators and generators.

Infinite and lazy sequences

Because an iterator only computes the next value when asked, it can describe sequences that are too large — or even infinite — to hold in memory. This is the main reason to write a custom iterator instead of just using an array:

javascript— editable
Warning

Never use spread ([...naturals()]) or for...of without a break on an infinite iterable — it will loop forever. Pull a finite number of values with next() instead.

Consuming Iterables

Once an object is iterable, the whole language opens up to it: any construct that accepts an iterable works with your custom type the same way it works with arrays.

Using Array.from()

The Array.from() method creates a new array from any iterable (or array-like) object. It also accepts an optional map function as a second argument, applied to every element as the array is built — handier than Array.from(it).map(fn) because it avoids a second pass:

javascript— editable

See JavaScript Map and Set for more on Set, and Array methods for what you can do once you have an array.

Spread Syntax with Iterables

Spread syntax (...) expands an iterable wherever arguments or elements are expected — merging arrays, copying, or passing items as function arguments:

javascript— editable

For the full picture of ... in both spread and collect positions, see Rest parameters and spread syntax.

Destructuring and rest

Destructuring assignment pulls values out of any iterable by position, and the rest pattern (...) gathers what's left into an array:

javascript— editable

Learn more in Destructuring assignment.

The String iterable and Unicode safety

Strings are iterable, and crucially the iterator walks Unicode code points, not 16-bit code units. That means surrogate-pair characters (emoji, some scripts) are kept intact — unlike indexing with [i] or older for loops over .length, which can split them:

javascript— editable

Whenever you need to count or split user-facing characters correctly, iterate the string (or spread it) rather than relying on .length. See the Strings chapter for more.

Summary

  • An object is iterable when it has a [Symbol.iterator]() method that returns an iterator — an object whose next() yields { value, done }.
  • Reach for a generator (function* / yield) instead of writing next() by hand; it's the shortest, least error-prone way to make something iterable.
  • Use for...of for the values of ordered/iterable data; use for...in only for the keys of plain objects.
  • Once iterable, your type plugs into spread, destructuring, rest, Array.from(it, mapFn), and many built-in APIs for free.
  • Iterators are lazy, so they can model infinite or huge sequences that an array never could.
  • Iterate strings (don't index them) to handle Unicode characters like emoji safely.

Practice

Practice
Which of the following statements about JavaScript iterables are correct?
Which of the following statements about JavaScript iterables are correct?
Was this page helpful?