Iterator
Baseline Widely available
This feature is well established and works across many devices and browser versions. It’s been available across browsers since July 2015.
Iterator
オブジェクトは、イテレーターの結果オブジェクトを返す next()
メソッドを提供することで、イテレータープロトコルに準拠したオブジェクトです。すべての組み込みイテレーターは Iterator
クラスを継承しています。 Iterator
クラスはイテレーターオブジェクト自身を返す [Symbol.iterator]()
メソッドを提供し、イテレーターを反復可能にしています。また、イテレーターを操作するためのヘルパーメソッドもいくつか提供しています。
解説
以下のものは、すべて JavaScript の組み込みイテレーターです。
- 配列イテレーター:
Array.prototype.values()
、Array.prototype.keys()
、Array.prototype.entries()
、Array.prototype[Symbol.iterator]()
、TypedArray.prototype.values()
、TypedArray.prototype.keys()
、TypedArray.prototype.entries()
、TypedArray.prototype[Symbol.iterator]()
、arguments[Symbol.iterator]()
で返されます。 - String イテレーター:
String.prototype[Symbol.iterator]()
で返されます。 - Map イテレーター:
Map.prototype.values()
、Map.prototype.keys()
、Map.prototype.entries()
、Map.prototype[Symbol.iterator]()
で返されます。 - Set イテレーター:
Set.prototype.values()
、Set.prototype.keys()
、Set.prototype.entries()
、Set.prototype[Symbol.iterator]()
で返されます。 - RegExp String イテレーター:
RegExp.prototype[Symbol.matchAll]()
、String.prototype.matchAll()
で返されます。 Generator
オブジェクト: ジェネレーター関数で返されます。- Segments イテレーター:
Intl.Segmenter.prototype.segment()
で返されるSegments
オブジェクトの[Symbol.iterator]()
メソッドで返されます。 - イテレーターヘルパーは、
Iterator.prototype.filter()
やIterator.prototype.map()
などのイテレーターヘルパーメソッドで返されます。
Web API はイテレーターを返すこともあります。 JavaScript のコアのイテレーターを再利用するものもあれば、自分自身でイテレーターを定義するものもあります。 例を示します。
- 配列風オブジェクト(
NodeList
など)は、配列イテレーターをkeys()
、values()
、entries()
、[Symbol.iterator]()
メソッドそれぞれで返します。 - Web API の Map 風オブジェクト、たとえば
Headers
は、独自のイテレーター型(Headers イテレーターなど)をkeys()
、values()
、entries()
、[Symbol.iterator]()
メソッドそれぞれで返します。 - Web API の Set 風オブジェクト、たとえば
FontFaceSet
は、独自のイテレーター型(FontFaceSet イテレーターなど)をkeys()
、values()
、entries()
、[Symbol.iterator]()
メソッドそれぞれで返します。
メモ: NodeIterator
やその他の古いインターフェイスはそのような名前が付いていますが、イテレータープロトコルや反復可能プロトコルには適合していません。
これらのイテレーターはそれぞれ個別のプロトタイプオブジェクトを持っており、特定のイテレーターが使用する next()
メソッドを定義しています。例えば、すべての String イテレーターオブジェクトは、隠しオブジェクトである StringIteratorPrototype
を継承しており、このオブジェクトは、その文字列をコードポイントごとに反復処理する next()
メソッドを持っています。また、 StringIteratorPrototype
は [Symbol.toStringTag]
プロパティを持っており、初期値は文字列 "String Iterator"
となります。このプロパティは Object.prototype.toString()
で使用します。同様に、他のイテレータープロトタイプも自分自身で [Symbol.toStringTag]
の値を持ち、それは上で指定された名前と同じです。
これらのプロトタイプオブジェクトはすべて Iterator.prototype
を継承しており、イテレーターオブジェクト自身を返す [Symbol.iterator]()
メソッドを提供し、イテレーターを反復可能にもしています。
イテレーターヘルパーメソッド
メモ:
これらのメソッドは、イテレーターヘルパーであり、反復処理可能オブジェクトヘルパーではありません。反復処理可能オブジェクトであるために要求されるのは、[Symbol.iterator]()
メソッドが存在することだけだからです。これらのメソッドをインストールするための共有プロトタイプはありません。
Iterator
クラス自体は、イテレーターを扱うためのいくつかのヘルパーメソッドを提供しています。例えば、次のようなことをしたくなるかもしれません。
const nameToDeposit = new Map([
["Anne", 1000],
["Bert", 1500],
["Carl", 2000],
]);
const totalDeposit = [...nameToDeposit.values()].reduce((a, b) => a + b);
これは、最初に Map.prototype.values()
が返すイテレーターを配列に変換し、次に Array.prototype.reduce()
メソッドを使用して合計を計算します。しかし、これはどちらも中間配列を作成し、その配列を 2 回反復処理します。代わりに、イテレーター自体の reduce()
メソッドを使用することができます。
const totalDeposit = nameToDeposit.values().reduce((a, b) => a + b);
このメソッドは、特にメモリー効率の面でより効率的かもしれません。なぜなら、中間値を記憶することなく、イテレーターを1度だけ反復処理するだけだからです。無限イテレーターで作業するには、イテレーターのヘルパーメソッドが必要です。
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);
seq
は無限であるため、配列に変換することはできません。その代わり、イテレーター自体の find()
メソッドを使用することができます。このメソッドは、条件を満たす最初の値を見つけるために必要な範囲で seq
を反復処理します。
次のように、配列のメソッドに類似した多くのイテレーターのメソッドが見つかります。
Iterator.prototype.drop()
と Iterator.prototype.take()
を組み合わせると、 Array.prototype.slice()
に似たものになります。
イテレーターヘルパーオブジェクト
メモ: 「イテレーターヘルパーオブジェクト」と「イテレーターヘルパーメソッド」は、 2 つの異なる概念です。イテレーターヘルパーオブジェクトは実行時に検出可能ですが、「イテレーターヘルパーメソッド」は、理解を助けるための一連のメソッドの名前にすぎません。「イテレーターヘルパー」は、コンテキストに応じて、オブジェクトまたはメソッドのどちらかを指す場合があります。
イテレーターヘルパーメソッドのうち、filter()
、flatMap()
、map()
、drop()
、take()
は、新しいイテレーターヘルパーオブジェクトを返します。 イテレーターヘルパーは、 Iterator
のインスタンスでもあり、これらのヘルパーメソッドを連結可能にします。 イテレーターヘルパーオブジェクトはすべて、イテレータープロトコルを実装する共通のプロトタイプオブジェクトを継承しています。
next()
-
基礎となるイテレーターの
next()
メソッドを呼び出し、結果にヘルパーメソッドを適用し、結果を返します。 return()
-
基になるイテレーターの
return()
メソッドを呼び出し、結果を返します。
イテレーターヘルパーは、基盤となるイテレーターと同じデータソースを共有しているため、イテレーターヘルパーを反復処理すると、基盤となるイテレーターも反復処理されます。イテレーターを「フォーク」して、反復処理を複数回できるようにする方法はありません。
const it = [1, 2, 3].values();
const it2 = it.drop(0); // 基本的にはコピー
console.log(it.next().value); // 1
console.log(it2.next().value); // 2
console.log(it.next().value); // 3
正規イテレーター
「イテレーター」には 2 種類あります。イテレータープロトコルに適合するオブジェクト(最小限、 next()
メソッドの存在のみが要求されます)と、ヘルパーメソッドが利用できる Iterator
クラスを継承するオブジェクトです。これらは互いに必要条件ではありません。 Iterator
クラスは next()
メソッドを定義していないため、 Iterator
を継承するオブジェクトは自動的にイテレーターになるわけではありません。代わりに、オブジェクトは next()
メソッドを自身で定義する必要があります。正規イテレーターとは、イテレータープロトコルに適合し、 Iterator
を継承するものを指します。ほとんどのコードでは、イテレーターは正規イテレーターであることを前提とし、反復可能オブジェクトは正規イテレーターを返すことを前提としています。正規イテレーターを作成するには、 Iterator
を継承するクラスを定義するか、 Iterator.from()
メソッドを使用するかしてください。
class MyIterator extends Iterator {
next() {
// …
}
}
const myIterator = Iterator.from({
next() {
// …
},
});
コンストラクター
Iterator()
-
イテレーターを作成する他のクラスによって継承するためのものです。単独で作成された場合はエラーが発生します。
静的メソッド
Iterator.from()
-
イテレーターまたは反復可能オブジェクトから、新しい
Iterator
オブジェクトを作成します。
インスタンスプロパティ
これらのプロパティは Iterator.prototype
で定義され、すべての Iterator
インスタンスで共有されます。
Iterator.prototype.constructor
-
インスタンスオブジェクトを作成するコンストラクター関数です。
Iterator
インスタンスの場合、初期値はIterator
コンストラクターです。 Iterator.prototype[Symbol.toStringTag]
-
[Symbol.toStringTag]
プロパティの初期値は文字列"Iterator"
です。このプロパティはObject.prototype.toString()
で使用されます。メモ: ウェブの互換性のため、多くの組み込みクラスの
[Symbol.toStringTag]
とは異なり、Iterator.prototype[Symbol.toStringTag]
は書き込み可能です。
インスタンスメソッド
Iterator.prototype.drop()
-
このイテレーターの開始位置で指定された要素数をスキップする、新しいイテレーターヘルパーオブジェクトを返します。
Iterator.prototype.every()
-
イテレーターによって生成されたすべての要素が、指定された関数で実装しているテストに合格するかどうかをテストします。
Iterator.prototype.filter()
-
新しいイテレーターヘルパーオブジェクトを返します。このオブジェクトは、指定されたコールバック関数が
true
を返すイテレーターの要素のみを生成します。 Iterator.prototype.find()
-
イテレーターが生成した最初の要素を返します。指定されたテスト関数を満たす値がない場合は、返値は
undefined
となります。 Iterator.prototype.flatMap()
-
元のイテレーターの各要素を取り、それを(別のイテレーターまたは反復可能オブジェクトに含まれている)マッピング関数に通し、マッピング関数から返された要素を生成する新しいイテレーターヘルパーオブジェクトを返します。
Iterator.prototype.forEach()
-
このイテレーターによって生成された各要素に対して、指定された関数を一度ずつだけ実行します。
Iterator.prototype.map()
-
新しいイテレーターヘルパーオブジェクトを返します。このオブジェクトは、マッピング関数によって変換されたイテレーターの要素を反復処理します。
Iterator.prototype.reduce()
-
イテレーターによって生成された各要素に対して、ユーザーが指定した「縮約」コールバック関数を実行し、前の要素の計算の返値を渡します。すべての要素に対して縮約を実行した最終結果は、単一の値となります。
Iterator.prototype.some()
-
イテレータ内の少なくとも 1 つの要素が、指定された関数で実装されているテストに合格しているかどうかを判定します。論理値を返します。
Iterator.prototype.take()
-
このイテレーターで指定された数の要素を反復処理し、その後終了する新しいイテレーターヘルパーオブジェクトを返します。
Iterator.prototype.toArray()
-
イテレーターから反復処理された要素で満たされた新しい配列インスタンス (
Array
) を作成します。 Iterator.prototype[Symbol.iterator]()
-
イテレーターオブジェクト自身を返します。これにより、イテレーターオブジェクトが反復可能にもなります。
例
イテレーターを反復可能オブジェクトとして使用
すべての組み込みイテレーターは反復可能でもあるので、for...of
ループの中で使うことができます。
const arrIterator = [1, 2, 3].values();
for (const value of arrIterator) {
console.log(value);
}
// Logs: 1, 2, 3
仕様書
Specification |
---|
ECMAScript Language Specification # sec-%iteratorprototype%-object |
ブラウザーの互換性
BCD tables only load in the browser