(Web関連用語)
https://developer.mozilla.org/ja/docs/Web/JavaScript/Guide/Iterators_and_generators
通常の関数は、単一の値だけを返す(もしくはなにも返さない)。
ジェネレータは、要求に応じて次々に複数の値、場合によっては無限の数の値を返す(“生み出す”)ことができる。それらは反復可能(iterables)と上手く機能し、データストリームを簡単に作成することができる。
ジェネレータ関数
ジェネレータを作成するには、特別な構文構造: function*、いわゆる “ジェネレータ関数” を使用する必要がある。
function* generateSequence() {
yield 1;
yield 2;
return 3;
}
generateSequence() が呼ばれたとき、コードは実行されない。代わりに、“ジェネレータ”と呼ばれる特別なオブジェクトを返す。
generator オブジェクトは“凍結された関数呼び出し”と捉えることができる。
// "ジェネレータ関数" は "ジェネレータオブジェクト" を生成する。
let generator = generateSequence();
作成時に、コードの実行は最初の部分で一時停止される。
ジェネレータのメインのメソッドは next() である。呼ばれると、最も近い yield 文まで実行を再開する。その後、実行は一時停止し、値は外部のコードに返却される。
例えば、ここではジェネレータを作成し、最初に戻される値を取得している:
function* generateSequence() {
yield 1;
yield 2;
return 3;
}
let generator = generateSequence();
let one = generator.next();
alert(JSON.stringify(one)); // {value: 1, done: false}
next() の結果は常にオブジェクトである:
- value:戻された値
- done:コードがまだ終わっていない場合は false、そうでなければ true
再び generator.next() を呼ぶと、実行が再開し、次の yield を貸す:
let two = generator.next();
alert(JSON.stringify(two)); // {value: 2, done: false}
そして、3回目を呼び出すと、実行は関数を終了する return 文に到達する。
let three = generator.next();
alert(JSON.stringify(three)); // {value: 3, done: true}
これでジェネレータが済んだ。done: true でそれが判断でき、value: 3 を最終結果として処理する。
新たな generator.next() 呼び出しはこれ以上意味をなさない。それを行っても、同じオブジェクト {done: true} が返却される。
ジェネレータを “ロールバック” する方法はない。しかし、generateSequence() 呼び出しによって、別の物を作ることはできる。
理解すべき最も重要なことは、ジェネレータ関数は通常の関数とは異なり、コードを実行しないことである。それらは “ジェネレータ工場(ファクトリー)” として機能する。function* の実行はジェネレータを返し、その後、ジェネレータに値を要求する。