コンテンツにスキップ

JavaScript/イテレータプロトコル

出典: フリー教科書『ウィキブックス(Wikibooks)』

イテレータプロトコル

[編集]

JavaScriptのイテレータプロトコルは、オブジェクトがfor...ofループなどの反復処理で使用される際に、反復可能であることを定義するための規則です。イテレータプロトコルを実装することで、カスタムオブジェクトを反復可能にし、配列やマップ、セットと同じようにfor...ofループを使用して繰り返し処理ができるようになります。

イテレータプロトコルは、主に2つのメソッドによって構成されます:

  1. next() メソッド
  2. 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が返され、donefalseの場合は反復を続けます。

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ループで順番に値を取り出すことができます。

イテレータプロトコルの利点

[編集]

イテレータプロトコルを実装することにより、次のような利点があります:

  • カスタムコレクションの反復処理: 独自のデータ構造を簡単に反復処理できるようにする。
  • 遅延評価: 必要に応じて値を生成するジェネレータを使用することで、メモリ効率を向上させる。
  • 無限シーケンスの扱いやすさ: 無限に続くシーケンス(例:自然数の列)を効率的に扱うことができる。