docs.rodeo

MDN Web Docs mirror

Iterator

{{JSRef}} 

An Iterator object is an object that conforms to the iterator protocol by providing a next() method that returns an iterator result object. All built-in iterators inherit from the Iterator class. The Iterator class provides a [Symbol.iterator]() method that returns the iterator object itself, making the iterator also iterable. It also provides some helper methods for working with iterators.

Description

The following are all built-in JavaScript iterators:

Web APIs may return iterators too. Some reuse core JavaScript iterators while others define their own iterators. For example:

Note: NodeIterator and other old interfaces are named as such but do not conform to the iterator protocol or iterable protocol.

Each of these iterators have a distinct prototype object, which defines the next() method used by the particular iterator. For example, all string iterator objects inherit from a hidden object StringIteratorPrototype, which has a next() method that iterates this string by code points. StringIteratorPrototype also has a [Symbol.toStringTag] property whose initial value is the string "String Iterator". This property is used in {{jsxref("Object.prototype.toString()")}} . Similarly, other iterator prototypes also have their own [Symbol.toStringTag] values, which are the same as the names given above.

All of these prototype objects inherit from Iterator.prototype, which provides a [Symbol.iterator]() method that returns the iterator object itself, making the iterator also iterable.

Iterator helper methods

[!NOTE] These methods are iterator helpers, not iterable helpers, because the only requirement for an object to be iterable is just the presence of a [Symbol.iterator]() method. There is no shared prototype to install these methods on.

The Iterator class itself provides some helper methods for working with iterators. For example, you may be tempted to do the following:

const nameToDeposit = new Map([
  ["Anne", 1000],
  ["Bert", 1500],
  ["Carl", 2000],
]);

const totalDeposit = [...nameToDeposit.values()].reduce((a, b) => a + b);

This first converts the iterator returned by {{jsxref("Map.prototype.values()")}}  to an array, then uses the {{jsxref("Array.prototype.reduce()")}}  method to calculate the sum. However, this both creates an intermediate array and iterates the array twice. Instead, you can use the reduce() method of the iterator itself:

const totalDeposit = nameToDeposit.values().reduce((a, b) => a + b);

This method may be more efficient, especially memory-wise, because it only iterates the iterator once, without memorizing any intermediate values. Iterator helper methods are necessary to work with infinite iterators:

function* fibonacci() {
  let current = 1;
  let next = 1;
  while (true) {
    yield current;
    [current, next] = [next, current + next];
  }
}

const seq = fibonacci();
const firstThreeDigitTerm = seq.find((n) => n >= 100);

You cannot convert seq to an array, because it is infinite. Instead, you can use the find() method of the iterator itself, which only iterates seq as far as necessary to find the first value that satisfies the condition.

You will find many iterator methods analogous to array methods, such as:

Iterator method Array method
{{jsxref("Iterator.prototype.every()")}}  {{jsxref("Array.prototype.every()")}} 
{{jsxref("Iterator.prototype.filter()")}}  {{jsxref("Array.prototype.filter()")}} 
{{jsxref("Iterator.prototype.find()")}}  {{jsxref("Array.prototype.find()")}} 
{{jsxref("Iterator.prototype.flatMap()")}}  {{jsxref("Array.prototype.flatMap()")}} 
{{jsxref("Iterator.prototype.forEach()")}}  {{jsxref("Array.prototype.forEach()")}} 
{{jsxref("Iterator.prototype.map()")}}  {{jsxref("Array.prototype.map()")}} 
{{jsxref("Iterator.prototype.reduce()")}}  {{jsxref("Array.prototype.reduce()")}} 
{{jsxref("Iterator.prototype.some()")}}  {{jsxref("Array.prototype.some()")}} 

{{jsxref("Iterator.prototype.drop()")}}  and {{jsxref("Iterator.prototype.take()")}}  combined are somewhat analogous to {{jsxref("Array.prototype.slice()")}} .

Iterator helper objects

Note: Iterator helper objects and iterator helper methods are two different concepts. An Iterator helper object is detectable at runtime, while “iterator helper method” is just a name for a set of methods for comprehension. Iterator helper may refer to either the object or the method, depending on the context.

Among the iterator helper methods, {{jsxref("Iterator/filter", "filter()")}} , {{jsxref("Iterator/flatMap", "flatMap()")}} , {{jsxref("Iterator/map", "map()")}} , {{jsxref("Iterator/drop", "drop()")}} , and {{jsxref("Iterator/take", "take()")}}  return a new Iterator Helper object. The iterator helper is also an Iterator instance, making these helper methods chainable. All iterator helper objects inherit from a common prototype object, which implements the iterator protocol:

The iterator helper shares the same data source as the underlying iterator, so iterating the iterator helper causes the underlying iterator to be iterated as well. There is no way to “fork” an iterator to allow it to be iterated multiple times.

const it = [1, 2, 3].values();
const it2 = it.drop(0); // Essentially a copy
console.log(it.next().value); // 1
console.log(it2.next().value); // 2
console.log(it.next().value); // 3

Proper iterators

There are two kinds of “iterators”: objects that conform to the iterator protocol (which, at its minimum, only requires the presence of a next() method), and objects that inherit from the Iterator class, which enjoy the helper methods. They do not entail each other — objects that inherit from Iterator do not automatically become iterators, because the Iterator class does not define a next() method. Instead, the object needs to define a next() method itself. A proper iterator is one that both conforms to the iterator protocol and inherits from Iterator, and most code expect iterators to be proper iterators and iterables to return proper iterators. To create proper iterators, define a class that extends {{jsxref("Iterator/Iterator", "Iterator")}} , or use the {{jsxref("Iterator.from()")}}  method.

class MyIterator extends Iterator {
  next() {
    // …
  }
}

const myIterator = Iterator.from({
  next() {
    // …
  },
});

Constructor

Static methods

Instance properties

These properties are defined on Iterator.prototype and shared by all Iterator instances.

Instance methods

Examples

Using an iterator as an iterable

All built-in iterators are also iterable, so you can use them in a for...of loop:

const arrIterator = [1, 2, 3].values();
for (const value of arrIterator) {
  console.log(value);
}
// Logs: 1, 2, 3

Specifications

{{Specifications}} 

Browser compatibility

{{Compat}} 

See also

In this article

View on MDN