Ch. 1 · JavaScript

JavaScript Iterators and Iterable Objects

JavaScript Iterators and Iterable Objects. Learn the reasoning, a practical example, common mistakes and an interview exercise.

~2 min readintermediateupdated Oct 3, 2026

An iterable provides Symbol.iterator returning an iterator. Next returns value and done. This protocol supports for-of, spread and collection constructors.

Step-by-step walkthrough

Step 1: Separate iterable from iterator

An iterable explains how to obtain a traversal; an iterator tracks one traversal’s progress. Symbol.iterator is the bridge. A next method alone does not necessarily make an object usable with for-of or spread.

Step 2: Define independent cursor state

If callers need repeatable traversal, each Symbol.iterator call should create fresh position state. An iterator that returns itself can be intentionally single-use. State the lifetime contract rather than assuming every iterable behaves like an array.

Step 3: Bound consumption

Lazy traversal lets consumers stop early, but spreading materializes all values. Infinite or very large sources need bounded iteration and a stopping condition. Resource-backed iterators also need a closure policy when a consumer abandons traversal.

Worked scenario

A range returns a fresh cursor for each traversal so two consumers can advance independently.

function range(start, end) {
  return {
    [Symbol.iterator]() {
      let current = start;
      return { next() {
        return current < end
          ? {value: current++, done: false}
          : {done: true};
      }};
    }
  };
}
console.log([...range(2, 5)]); // [2, 3, 4]
JavaScript

Walk through the example

The end is exclusive. Each traversal receives its own current variable, so the same range can be traversed twice independently. Returning done true marks completion; consumers should not treat that completion record as another ordinary value. The range itself does not eagerly allocate the numbers.

Common mistake

An iterator can be single-use. Spreading an infinite iterable never completes, and large spreads lose incremental processing.

Verify the behavior

Test an empty interval, one value and two concurrent iterators. Check that advancing one iterator does not advance the other. Define how reversed bounds should behave, and avoid spreading a source that may be infinite.

Interview exercise

Make an object work with for-of.

Answer and reasoning

Provide Symbol.iterator and a valid next result; defining next alone does not necessarily make the object iterable.

Follow-up discussion

Why use an iterator instead of an array? It can deliver values incrementally and avoid storing an entire generated sequence. Does laziness guarantee low memory? No: consumers can still buffer every value, and the iterator may retain substantial source state.

Continue learning

Compare the scenario with the JavaScript interview questions and test your understanding with the JavaScript MCQs. For terminology and implementation details, consult the reference material.

More in JavaScript

read ✓JavaScript · mid

JavaScript Date and Timezone Pitfalls

Parse and format dates without timezone surprises: zero-based months, date-only versus date-time parsing, and why UTC storage avoids drift.

~3 min readread →
read ✓JavaScript · mid

JavaScript Number Precision and BigInt

Why 0.1 + 0.2 is not 0.3, where safe integer range ends, and when BigInt is the right tool for large identifiers and money.

~2 min readread →
esc