generator

【function* yield】ジェネレーターとは?【JavaScript】

ジェネレーター(Generator)とは

ジェネレーターとは「生成器」と言う意味ですが、その通り呼ばれるたびに任意の地点で値を生成して渡す関数であり、イテレータのようなものです。

ES6(ES2015)で追加されました。

無限ループを作ったり、関数の処理を途中で止めたり再開させたりと色々便利な機能です。

最近では、ReduxのMiddlewareであるredux-sagaで利用されたりしています。

 

使ってみる

早速下のようなコードを実行してみます。

function* gen() { 
  yield 1;
  yield 2;
  yield 3;
}

var g = gen(); // ここでは実行されない
console.log(g.next());
console.log(g.next());
console.log(g.next());
console.log(g.next());

結果はこちら

Object {
  done: false,
  value: 1
}
Object {
  done: false,
  value: 2
}
Object {
  done: false,
  value: 3
}
Object {
  done: true,
  value: undefined
}

コードを解説していきます。

まず、ジェネレーターを利用する時は、function*と言うように書いてジェネレーター関数を作ります。

次に、yieldと言うものがありますが、これはその時点での値を生成して返すものです。

ジェネレーター関数は、var g = gen()と記述しただけでは実行されずません。

next()メソッドを利用することでyieldにたどり着くまで処理を実行し、yieldを見つけたところでその値を返します。

結果を見るとわかるように、yieldで返される値にはdoneと言うものがあり、関数内にまだyieldが存在する時はfalse、関数内の最後ののyieldまでたどり着いたらtrueを返すようになります。

最後の実行では値を返すyieldがないのでもちろん値はundefinedとなります。

 

無限ループはこんな感じで作ることができます。

function* gen() {
  a = 0;
  while(true) {
    yield a += 1;
  }
}
  
var g = gen();
console.log(g.next()); // 1
console.log(g.next()); // 2
console.log(g.next()); // 3
console.log(g.next()); //4

 

また、yield*をつけたyield*と言うものもあり、これは別のジェネレーターを呼び出すことができます。

function* gen1(){  
   yield console.log("2");
   yield console.log("3");
};
function* gen2(){  
   yield console.log("1");
   yield* gen1();
   yield console.log("4");
};

var g = gen2();
g.next() // 1;
g.next() // 2;
g.next() // 3;
g.next() // 4;

また、これはジェネレーターが生成したイテレータオブジェクトを渡されているので、配列などのイテレータオブジェクトを渡すことでも機能します。

function* gen(){  
   yield* ["red", "blue", "green"];
};

var g = gen();
console.log(g.next().value); // red
console.log(g.next().value); // blue
console.log(g.next().value); // green

 

うまく使えばとても便利なのでぜひ使ってみましょう!

 

Reduxの基礎知識① Action,Reducers,Store【初心者向け】