【JavaScript】イテレータ(Iterator)とジェネレータ(Generator)
イテレータ(Iterator)とは
イテレータとは、コレクション(配列、オブジェクトなど)の要素を順番に処理するためのオブジェクトです。イテレータは、コレクションの各要素にアクセスするメソッド(主に`next()`)を提供し、要素を一つずつ取り出すことができます。イテレータは、通常、`Symbol.iterator`という特別なメソッドを持つオブジェクトによって提供されます。
例えば、配列は標準でイテレータを持っています。このイテレータは、配列の要素を順番に取り出すために使用されます。
イテレータの例
次に、簡単なイテレータの例を示します。
const arr = [10, 20, 30];
const iterator = arr[Symbol.iterator]();
console.log(iterator.next()); // { value: 10, done: false }
console.log(iterator.next()); // { value: 20, done: false }
console.log(iterator.next()); // { value: 30, done: false }
console.log(iterator.next()); // { value: undefined, done: true }
上記の例では、`arr[Symbol.iterator]()`を使用して配列のイテレータを取得し、`next()`メソッドで要素を一つずつ取り出しています。`next()`メソッドは、`value`と`done`プロパティを含むオブジェクトを返します。`done`が`true`になると、イテレータが終了したことを意味します。
ジェネレータ(Generator)とは
ジェネレータは、イテレータの特殊なバージョンです。ジェネレータは関数であり、通常の関数とは異なり、`yield`キーワードを使用して実行を一時停止し、後で再開できます。この特性により、ジェネレータは「遅延評価」を行い、大量のデータを一度にメモリにロードすることなく順番に生成できます。ジェネレータ関数は、呼び出すとジェネレータオブジェクトを返し、そのオブジェクトを使って要素を生成します。
ジェネレータ関数の基本的な構文は以下のようになります。
function* exampleGenerator() {
yield 1;
yield 2;
yield 3;
}
上記の例では、`function*`を使ってジェネレータ関数を定義し、`yield`キーワードで値を返しています。ジェネレータ関数を呼び出すと、ジェネレータオブジェクトが返されます。
ジェネレータの例
次に、ジェネレータの使用例を示します。
const gen = exampleGenerator();
console.log(gen.next()); // { value: 1, done: false }
console.log(gen.next()); // { value: 2, done: false }
console.log(gen.next()); // { value: 3, done: false }
console.log(gen.next()); // { value: undefined, done: true }
上記のコードでは、`exampleGenerator`ジェネレータ関数を呼び出し、`gen.next()`を使って生成された値を順番に取り出しています。`next()`メソッドもイテレータと同様に`value`と`done`プロパティを持つオブジェクトを返します。
イテレータとジェネレータの違い
イテレータとジェネレータにはいくつかの重要な違いがあります。
- イテレータ: コレクションの各要素を順番に取り出すためのオブジェクトです。通常、配列やオブジェクトに関連付けられています。
- ジェネレータ: `yield`を使用して関数内で遅延評価を行い、実行を一時停止して後で再開できます。ジェネレータ関数は、`function*`という構文で定義されます。
- 状態の保持: イテレータは外部の状態を持たず、次の要素を返すために常にそのまま繰り返し呼ばれます。ジェネレータは内部状態を保持し、`yield`で一時停止した地点から実行を再開できます。
したがって、ジェネレータはより柔軟で強力な機能を提供し、複雑なデータの生成や処理に適しています。