JavaScript/イテレータプロトコル
イテレータプロトコル
[編集]JavaScriptのイテレータプロトコルは、オブジェクトがfor...ofループなどの反復処理で使用される際に、反復可能であることを定義するための規則です。イテレータプロトコルを実装することで、カスタムオブジェクトを反復可能にし、配列やマップ、セットと同じようにfor...ofループを使用して繰り返し処理ができるようになります。
イテレータプロトコルは、主に2つのメソッドによって構成されます:
next()メソッドSymbol.iteratorメソッド
next() メソッド
[編集]イテレータオブジェクトは、next()メソッドを持つ必要があります。このメソッドは、反復処理される各値を提供します。next()は、doneプロパティとvalueプロパティを含むオブジェクトを返します。
value: 次に返される値done: イテレーションが終了したかどうかを示すブール値(trueならば反復終了、falseならば続行)
例えば、次のジェネレータ関数は、next()メソッドの挙動を示しています。
function* counter() { yield 1; yield 2; yield 3; } const iterator = counter(); console.log(iterator.next()); // { value: 1, done: false } console.log(iterator.next()); // { value: 2, done: false } console.log(iterator.next()); // { value: 3, done: false } console.log(iterator.next()); // { value: undefined, done: true }
counter()は、yieldを使って順番に値を返します。next()メソッドが呼び出されるたびに、その時点のvalueが返され、doneがfalseの場合は反復を続けます。
Symbol.iterator メソッド
[編集]イテレータプロトコルを満たすためには、対象のオブジェクトがSymbol.iteratorメソッドを持っている必要があります。このメソッドは、反復可能なオブジェクトに対してイテレータを返すメソッドです。
例えば、配列のイテレータは以下のように定義されています。
const arr = [1, 2, 3]; const iterator = arr[Symbol.iterator](); console.log(iterator.next()); // { value: 1, done: false } console.log(iterator.next()); // { value: 2, done: false } console.log(iterator.next()); // { value: 3, done: false } console.log(iterator.next()); // { value: undefined, done: true }
Symbol.iteratorメソッドは、反復可能なオブジェクト(配列、文字列、セット、マップなど)で標準で実装されています。このメソッドを自分で実装することで、カスタムオブジェクトもイテレータとして使えるようになります。
イテレータプロトコルのカスタム実装
[編集]独自のイテレータプロトコルを実装したい場合、next()メソッドとSymbol.iteratorメソッドを提供する必要があります。例えば、以下のコードではカスタムオブジェクトに対してイテレータを実装しています。
const customIterable = { from: 1, to: 3, [Symbol.iterator]() { let current = this.from; const last = this.to; return { next() { if (current <= last) { return { value: current++, done: false }; } else { return { value: undefined, done: true }; } } }; } }; for (const num of customIterable) { console.log(num); // 1, 2, 3 }
この例では、customIterableというオブジェクトがSymbol.iteratorを実装しており、next()メソッドを使用して、1から3までの数値を順番に返します。
イテレータと反復可能なオブジェクト
[編集]イテレータプロトコルを実装したオブジェクトは、反復可能(iterable)なオブジェクトとなります。反復可能オブジェクトは、for...ofループを使って反復処理することができます。反復可能オブジェクトは、[Symbol.iterator]()メソッドを持っており、これによってイテレータを取得することができます。
const iterable = ['a', 'b', 'c']; for (const item of iterable) { console.log(item); // a, b, c }
この場合、配列iterableは反復可能なオブジェクトであり、for...ofループで順番に値を取り出すことができます。
イテレータプロトコルの利点
[編集]イテレータプロトコルを実装することにより、次のような利点があります:
- カスタムコレクションの反復処理: 独自のデータ構造を簡単に反復処理できるようにする。
- 遅延評価: 必要に応じて値を生成するジェネレータを使用することで、メモリ効率を向上させる。
- 無限シーケンスの扱いやすさ: 無限に続くシーケンス(例:自然数の列)を効率的に扱うことができる。