调用生成器函数会返回一个生成器对象,每次调用生成器对象的 next 方法会执行函数到下一次 yield 关键字停止执行,并且返回一个 { value: Value, done: boolean }的对象。本质是协程在 ES6 的实现。
基础语法 1 2 3 4 5 6 7 8 9 10 11 12 13 function * gen ( ) {  yield  1 ;   yield  2 ;   yield  3 ; } let  g = gen ();console .log (g.next ()); console .log (g.next ()); console .log (g.next ()); console .log (g.next ()); console .log (g.next ()); 
 
首先调用gen() 生成器函数返回 g 生成器对象。 
其次返回的 g 生成器对象中拥有一个 next 的方法。 
每当我们调用 **g.next()**方法时,生成器函数紧跟着上一次进行执行,直到函数碰到 yield 关键值。  
yield 关键字会停止函数执行并将 yield 后的值返回作为本次调用 next 函数的 value 进行返回。 
同时,如果本次调用g.next()导致生成器函数执行完毕,那么此时 done 会变成 true 表示该函数执行完毕,反之则为 false 。 
 
进阶语法 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 function * gen ( ) {  const  a = yield  1 ;   console .log (a, 'this is a' );   const  b = yield  2 ;   console .log (b, 'this is b' );   const  c = yield  3 ;   console .log (c, 'this is c' );   return  'res' ; } let  g = gen ();console .log (g.next ()); console .log (g.next ('param-a' )); console .log (g.next ('param-b' )); console .log (g.next ('param-c' )); console .log (g.next ()); 
 
定义一个生成器函数,并创建一个生成器对象。 
第一次调用 g.next()方法时,函数执行到 yield 1并中断函数执行,由于代码中断,a的赋值语句并没有被执行。 
第二次调用g.next()方法时,next 接受传参传入一个字符串param-a,函数执行时从上一次中断的地方开始继续执行,也就是执行 a的赋值语句,从打印结果来看,a被赋值为字符param-a。 
第三次调用g.next()方法并传入字符串param-b时,结果同样是变量b被赋值为param-b。 
第四次调用g.next()方法与第二第三次的区别是,return语句作为返回值语句取代了yield语句,所以执行结果是{ value: 'res', done: true }。 
第五次调用g.next(),由于生成器函数已经执行完毕,所以打印{ value: undefined, done: true }。 
 
从上述的分析中可以得出两个结论:
当我们为 next 传递值进行调用时,传入的值会被当作上一次生成器函数暂停时 yield 关键字的返回值处理。 
当生成器函数执行完毕时,原本本次调用 next 方法返回的{done:true,value:undefined}由于return语句变为了{ done:true,value:'res'}。 
 
实现 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 const  generatorWrap  = (fn ) => {  const  ctx = {     next : 0 ,      sent : "" ,      done : false ,           stop ( ) {       this .done  = true ;     },   };   return  {     next (param ) {              ctx.sent  = param;              const  value = fn (ctx);              return  {         done : ctx.done ,         value,       };     },   }; }; function  gen ( ) {  let  a, b, c;   return  generatorWrap (function  (ctx ) {     switch  ((ctx.prev  = ctx.next )) {       case  0 :         ctx.next  = 1 ;         return  1 ;       case  1 :         a = ctx.sent ;         console .log (a, 'this is a' );         ctx.next  = 2 ;         return  2 ;       case  2 :         b = ctx.sent ;         console .log (b, 'this is b' );         ctx.next  = 3 ;         return  3 ;       case  3 :         c = ctx.sent ;         console .log (c, 'this is c' );       case  'end' :         return  ctx.stop ();     }   }) } const  g = gen ();console .log (g.next ());console .log (g.next ('param-a' ));console .log (g.next ('param-b' ));console .log (g.next ('param-c' ));