Iterator.from()

Wrap any iterable or bare iterator object in a real Iterator so the helper methods become available.

Signature
Iterator.from(object)
  • Added in JavaScript ES2025 (Baseline March 2025)

Parameters

ParameterTypeDescription
$objectIterable | IteratorAn object implementing the iterable protocol (a [Symbol.iterator]() method) or the iterator protocol (a next() method).

Return value

IteratorAn Iterator object. If object is already an instance of Iterator it is returned unchanged; if it is iterable its [Symbol.iterator]() method is called; otherwise the raw iterator is wrapped in a new object that inherits from Iterator.prototype.

Errors

Throws a TypeError if the argument is not an object and is not a string, or if it implements neither the iterable nor the iterator protocol.

Iterator helpers such as map() and take() live on Iterator.prototype. Built-in iterators — the ones returned by array.values(), set.values(), map.entries() and generator functions — inherit from it, so they get the helpers for free. Hand-written iterators usually do not: an object literal with just a next() method satisfies the iterator protocol but inherits from Object.prototype, so .map() on it is a TypeError. This is the bridge.

When to reach for it

  • You are consuming an iterator from a library or a DOM-style API and want to chain helpers onto it.
  • You wrote a stateful next() by hand and do not want to rewrite it as a generator.
  • You have an iterable and want a single iterator you can pull from in several places, rather than restarting it.

What trips people up

It does not accept array-likes. Array.from({ length: 3 }) works; Iterator.from({ length: 3 }) throws, because a length property is not an iteration protocol. Passing a plain object is the most common mistake.

It also does not copy. The returned wrapper delegates to the same underlying iterator, so consuming the wrapper consumes the original — and calling return() on the wrapper closes the original too.

Example

Try it yourself
Loading editor…
Press Run to execute the code.

When to use it

  • Chain map/filter/take onto a hand-written object that only has a next() method
  • Adapt a third-party iterator whose prototype chain predates iterator helpers
  • Turn an iterable into a single shared, resumable iterator for staged consumption

Frequently asked questions

What is the difference between Iterator.from() and Array.from()?

Iterator.from() returns a lazy iterator that produces values on demand, while Array.from() eagerly materialises every value into an array. Use Iterator.from() when the source is long or infinite, or when you want to chain helpers before collecting; use Array.from() when you want the whole thing in memory now. Array.from() also accepts array-likes, which Iterator.from() rejects.

Why does my custom iterator not have .map() or .filter()?

Because it inherits from Object.prototype rather than Iterator.prototype, where the helpers live. Object literals with a next() method satisfy the iterator protocol but sit outside that prototype chain. Pass it through Iterator.from() to get a wrapper that inherits the helpers, or write it as a generator function, whose result already inherits them.

Does Iterator.from() copy the underlying iterator?

No. The wrapper delegates every next() call to the original iterator, so pulling values from the wrapper advances the original, and closing one closes the other. If you need two independent passes, collect the values with toArray() and iterate the array twice.

More examples

Iterables pass straight through

For a value that is already an Iterator the same object comes back — identity holds. For a plain iterable, from() obtains its iterator. Strings are iterable by code point, so take(2) yields "h" and "é" rather than half a surrogate pair.

Example · javascript
const set = new Set(["a", "b", "c"]);

// Set already yields a proper iterator, so from() just returns it.
const it = set.values();
console.log(Iterator.from(it) === it); // true

// Given the iterable itself, from() calls [Symbol.iterator]().
console.log(Iterator.from(set).toArray()); // ["a", "b", "c"]
console.log(Iterator.from("héllo").take(2).toArray()); // ["h", "é"]

Rejecting array-likes

Array.from() understands the length/index convention; Iterator.from() does not and throws. Converting through Array.from() first is the usual fix.

Example · javascript
const arrayLike = { length: 3, 0: "x", 1: "y", 2: "z" };

console.log(Array.from(arrayLike)); // ["x", "y", "z"]

try {
  Iterator.from(arrayLike);
} catch (err) {
  console.log(err.constructor.name); // "TypeError"
}

// Fix: give it something iterable.
console.log(Iterator.from(Array.from(arrayLike)).toArray());

Discussion

  • Be the first to comment on this lesson.