ユーザ用ツール

サイト用ツール


javascript:generator

文書の過去の版を表示しています。


Generator

Generator(ジェネレータ)はECMAScript 6で追加された新機能。

ジェネレータは、Iterator(イテレータ)の反復処理において内部の状態管理が必要となる場合に、より簡単な状態管理を行うための機能としてpythonに用意されているジェネレータを真似たものである。

ジェネレータを用いた反復処理では「次の値の取り出し」と「取り出した値の処理」を交互に繰り返される。このとき「次の値の取り出し」を行った後「取り出した値の処理」が完了するまでジェネレータ関数の中では手続きの流れが一時中断される。

通常JavaScriptでは実現できない中断という動作が非同期処理のより良いコーディング手法として注目されている。

ジェネレータの動作

function* f() {
   yield "a";
   yield "b";
   yield "c";
}
 
var g = f();             // g => [Object: generator]
console.log(g.next());   // => "a"
console.log(g.next());   // => "b"
console.log(g.next());   // => "c"
console.log(g.next());   // => { value: undefined, done: true }
  1. キーワード function* でジェネレータ関数を定義
  2. ジェネレータ関数を実行するとGeneratorオブジェクトが得られる。
  3. Generator#nextを呼ぶとジェネレータ関数の最初のyield式まで実行され、nextがyield式の評価結果を返す。
  4. 再度Generator#nextを呼ぶと次のyield式まで実行される
    • 繰り返し
  5. Generator#nextが呼ばれ、ジェネレータ関数の末尾まで到達すると { value: undefined, done: true } を返す

ジェネレータの例

フィボナッチ数列を生成するジェネレータ

function* fibonacci(limit = Infinity) {
    var count = 0;
    var a = 1;
    var b = 1;
    while(count++ < limit) {
        let c = a + b;
        a = b;
        b = c;
        yield c;        
    }
}
 
for (let i of fibonacci(5)) {
   console.log(i)
}

結果

2
3
5
8
13

Rangeを生成するジェネレータ

function* range(a, b) {
    for(var i = a; i <= b; i++) {
        yield i;
    }
}
 
for (let i of range(3,7)) {
   console.log(i)
}

結果

3
4
5
6
7

非同期処理

ジェネレータを用いた非同期処理

var g = (function* () {
   console.log(1);
   var x = yield setTimeout(function() { console.log(2); g.next(3); }, 1000);
   console.log(x);
   var y = yield setTimeout(function() { console.log(4); g.next(5); }, 2000);
   console.log(y);
})();
g.next();

結果

1  // ここで1秒待つ
2 
3  // ここで2秒待つ
4
5
javascript/generator.1388498037.txt.gz · 最終更新: 2013/12/31 13:53 by nullpon