JSジェネレータ-generator


個人ブログを参照してください.http://www.zhuzhuman.com/nav-1/type-1/article/23.html
generator(ジェネレータ)はES 6規格で導入された新しいデータタイプです.最大の特徴は、関数の実行を一時停止することです.一つのgeneratorは関数のように見えますが、違いは関数名の前に一つの星があります.yieldコマンドに合わせて、実行を一時停止する機能を実現します.
1.基本的な使い方
function* testGenerator(a) {
  console.log('a');
  yield ++a; 

  console.log('b');
  yield ++a;
	
  console.log('c');
  return ++a;	
  console.log('d');
}

var gener = testGenerator(5);	//     log     ,         ,
var gener2 = testGenerator(1);	// gener   gener2       ,

console.log(gener);	// testGenerator{}   (generator  ),           

var yield1 = gener.next();	// a  (     a,   yield  log   )
console.log(yield1);  // {value: 6, done: false} 	next                   
console.log(yield1.value);	// 6	(value yield     )
console.log(yield1.done);	// false	(done yield     ,false          ,     )


var yield2 = gener.next();  // b  (    b,          yield          ,    yield  )
console.log(yield2);  // {value: 7, done: false}
console.log(yield2.value);  // 7	(      7,               yield     (  a=6)   )
console.log(yield2.done);  // false	()

var yield3 = gener.next();  // c  (    c,          yield          , return  )
console.log(yield3);  // {value: 8, done: true}
console.log(yield3.value);  // 8
console.log(yield3.done);  // true

var yield4 = gener.next();  // (    ,     renturn         )
console.log(yield4);  // {value: undefined, done: true}  (   return,    next()       undefind)
2.next方法
  • yield文に出会うと、後の動作の実行を一時停止し、yieldの後に続くその表現の値を返した対象のvalue属性の値とします.
  • 再度nextメソッドを呼び出した場合、次のyield文が発生するまで継続して実行します.
  • 新しいyield文がない場合は、return文が終わるまで関数が実行され、return文の後の表式の値を、返す対象となるvalue属性値として返します.
  • この関数がreturn文を持っていない場合、リターンされるオブジェクトのvalue属性値はundefinedである.
  • nextメソッドは、パラメータ、nextメソッドパラメータの役割があります.前のyield文を上書きする値です.
  • function* testNext() {
      var a = 1;
      var b = yield ++a;
      console.log(b);
    
      var c = yield ++a;
      console.log(c);
    
      return ++a;
    }
    
    var gener3 = testNext();
    
    // var v1 = gener3.next(3);  //      next     ,            yield   ,          
    
    var v1 = gener3.next();  // (       :var b = yield ++a;            ,      yield ++a,   ++a(2)     ,    b      。)
    console.log(v1);  // {value: 2, done: false}
    
    var v2 = gener3.next(6);  // 6	     next,  ,   ,      yield   (++a  2)       6,        , b  ,      b = 6
    console.log(v2);  // {value: 3, done: false}      yield   ,a   2,       yield    ++a    ,    3
    
    var v3 = gener3.next(10);  // 10
    console.log(v3);  // {value: 4, done: true},     
    
    3.スロットル方法
  • は関数の外にエラーを投げ、Generator関数の中で捕獲する.
  • function* testThrow() {
      console.log(1)
      yield 1;
    
      try {
        console.log(2)
        yield 2;
        console.log(3)
        yield 3;
      } catch (e) {
        console.log('   catch:' + e);
      }
      console.log(4);
      yield 4;
    
      try{
        console.log(5);
        yield 5;
      } catch (e) {
        console.log('   catch:' + e);
      }
    	
      console.log(6);
      return 6;
    }
    
    var gener4 = testThrow();
    var t1 = gener4.next();  // 1
    console.log(t1);  // {value: 1, done: false}
    // gener4.throw('        ^_^!');	//   :Uncaught         ^_^!; 	(     next   try...catch...         ,       ,         。      next     {value: undefined, done: true})
    
    var t2 = gener4.next();  // 2
    console.log(t2);  // {value: 2, done: false}
    gener4.throw('    1   catch  ^_^');  //    catch:    1   catch  ^_^    (      , generator  catch     )
    // 4 	//        ,           next()   ,         ,  try        yield       ,  ,  try          yield  
    
    // gener4.throw('    2    catch  ^_^');		// Uncaught     2    catch  ^_^	(               ,          yield 4;  )
    
    var t3 = gener4.next();  // 5
    console.log(t3);  // {value: 5, done: false}
    gener4.throw('    3   catch  ^_^');  //    catch:    3   catch  ^_^
    // 6  // catch   ,      next();      ,      return 6;  
    
    var t4 = gener4.next();
    console.log(t4);  // {value: undefined, done: true}   (   catch  ,   return   ,       next    {value: undefined, done: true})
    
    4.return方法
  • は、与えられた値(今回のyieldをカバーする値)を返し、Generator関数を巡回して終了することができる.
  • function* testReturn() {
      yield 'a';
      yield 'b';
      yield 'c';
    }
    
    var gener5 = testReturn();
    
    var g1 = gener5.next();
    console.log(g1);  // {value: "a", done: false}
    
    var g2 = gener5.return('e');
    console.log(g2);  // {value: "e", done: true}  (     yield  b       e,   generator    ,)
    
    var g3 = gener5.next();
    console.log(g3);  // {value: undefined, done: true}	(       )
    
    5.for…of…
  • for...of...サイクルは、Generator関数によって生成されたIteratorオブジェクトを自動的に巡回することができ、このときはnextメソッド
  • を呼び出す必要がなくなります.
    function* testForOf() {
      yield 'J';
      yield 'Q';
      yield 'K';
      return 'A';
    }
    
    var gener6 = testForOf();
    
    for(var f of gener6) {
      console.log(f);
      // J 	(for...of        Generator      Iterator  ,         next  。)
      // Q 		
      // K  (  next        done   true,for...of      ,         ,       A)
    }
    
    var f1 = gener6.next();
    console.log(f1);  // {value: undefined, done: true}	(for...of...      next, for    ,generator      done:true    )
    
    6.yield文
  • yield文は、functionの作用領域にしか使用できません.functionの内部に他の一般関数が定義されている場合、関数内部では、yield文を使用することができません.
  • yield*はGenerator関数の内部にあり、別のGenerator関数
  • を呼び出します.
    function* testYield() {
      yield 'x';
    
      // function inFn() {
      // yield 'y';   // Uncaught SyntaxError: Unexpected string    (  ,          yield)
      // }
    
      yield 'y';
    }
    
    function* testYield2() {
      yield 'xx';
      testYield();
      yield 'yy';
    }
    
    for(var m of testYield2()) {
      console.log(m);
      // xx
      // yy
      // ( testYield2      testYield   )
    }
    
    function* testYield3() {
      yield 'xxx';
      yield* testYield();
      yield 'yyy';
    }
    
    for(var n of testYield3()) {
      console.log(n);
      // xxx
      // x
      // y
      // yyy
      // (yield*  testYield3      testYield   )
    }