LOG

ジェネレータ関数

ジェネレーターは処理を抜け出すことも後から再帰することもできる関数です。ジェネレーターのコンテキスト (変数の値)は再帰しても保存されます。
引用:function* – JavaScript | MDN

以下の記事も読んだ方が良いです。

function* xxx(){
    ...
}

とfunctionの後にアスタリスクを付けて定義します。
ジェネレータ関数は呼び出しても直ぐに実行はされず、iteratorオブジェクトを返し、iteratorのnext()メソッドが呼ばれることで実行されます。
またコンテキストは保存されます。
next()メソッドは生成された値を含むvalueプロパティとジェネレーターが最後の値を持つかを示すdoneプロパティを持つオブジェクトを返します。

function* generator1(){
    let index = 0;
    return index;
}

let gen1 = generator1();

console.log(gen1.next());
// -> Object {value: 0, done: true}

console.log(gen1.next());
// -> {value: undefined, done: true}
// ↑コンテキストが保存されているのでvalueはundefinedになる。

console.log(generator1().next());
// -> Object {value: 0, done: true}

yieldを使う

yield演算子はジェネレータ関数の一時停止と再開などに利用できます。

function* generator2(){
    let index = 0;
    yield index++;
    yield index++;
}

let gen2 = generator2();

console.log(gen2.next());
// -> Object {value: 0, done: false}
// ↑ yieldで処理を中断したのでdoneはfalseになる

console.log(gen2.next());
// -> Object {value: 1, done: false}
// -> 中断したyieldの次の行から処理がスタートする。コンテキストが保存されているのでvalueは1になる。

console.log(gen2.next());
// -> Object {value: undefined, done: true}

このような書き方だと処理回数分yieldを書かないと行けないので現実的ではありません。
なので実際に使う場合は以下のようにします。

function* generator2(){
    let index = 0;
    while(true) // 条件がtrueなので終わらないwhileになる。 for(;;)とかでも良い。
        yield index++;
}

let gen2 = generator2();

console.log(gen2.next().value);
// -> 0
console.log(gen2.next().value);
// -> 1
console.log(gen2.next().value);
// -> 2

yield*を使う

yield*は他のgeneratorに委任します。

function* anotherGenerator(i) {
    yield i + 1;
    yield i + 2;
    yield i + 3;
}
function* generator(i){
    yield i;
    yield* anotherGenerator(i);
    yield i + 10;
}

var gen = generator(10);

console.log(gen.next().value); // 10
console.log(gen.next().value); // 11
console.log(gen.next().value); // 12
console.log(gen.next().value); // 13
console.log(gen.next().value); // 20

引用:function* – JavaScript | MDN

for…ofで使う

for…of構文はArray、Array に類似するオブジェクト、イテレータやジェネレータに反復処理を行えます。

function* generator2(){
    let index = 0;
    while(true)
        yield index++;
}

for(let val of generator2()){
    if(val > 5) // 無限ループに陥るので
        break;
    console.log(val);
}