考虑以下场景:
var a = 1;
var b = 2;function foo(){a++;b = b * a;a = b + 3;
}function bar(){b--;a  = 8 + b;b = a * 2;
}foo();
bar();
console.log(a, b);   // 11 22bar();
foo();
console.log(a, b);    // 183 180
对于上面的两个函数foo和bar,它们中的任何一个,一旦开始了就会一直执行下去直至完毕.
 倘若,我们想在foo中a++后,暂停一下在去执行bar中的某个语句… 可以使用ES6提供的yield语句.
 改变如下:
var a = 1;
var b = 2;function *foo(){    // *是生成器的标志a++;yield;b = b * a;a = (yield b) +3;
}function *bar(){b--;yield;a = (yield 8) + b;b = a * (yield 2);
}// 调用:foo执行完,在执行bar()
var s1 = foo();   // 初始化迭代器.
s1.next();  
console.log(a, b);  // 2 2 
s1.next();
console.log(a, b);  // 2 4// 还有最后一个 a = (yield b) + 3;
s1.next();   // "预计"执行后会得到 7 4 
console.log(a, b);  // 实际上  NaN  4// 诶????
// 实际执行yield b时,并得不到b的值因此会返回NaN. 于是a就是NaN// 改进如下(foo中有2个yield, 因此会有3个next)
var s1 = foo();
var val1 = s1.next().value;
console.log(a, b);
val1 = s1.next(val1).value;
console.log(a, b);
val1 = s1.next(val1).value;
console.log(a, b);// 运行bar,(bar中有3个yield,会有4个next调用)
var s2 = bar();  
var val2 = s2.next().value;
console.log(a, b);
val2 = s2.next(val2).value;
console.log(a, b);
val2 = s2.next(val2).value;
console.log(a, b);
val2 = s2.next(val2).value;
console.log(a, b);

 可以看到,和正常函数执行结果是一样的…
 还注意到.上述好多赋值语句是重复的,因此可以考虑构造一个辅助函数step,用于将yield返回的值原样的传入.
// step
function step(gen){var it = gen();var last;return function(){last = it.next(last).value;}
}
接下来使用step,先执行bar,后执行foo
var s1 = step(bar);
var s2 = step(foo);s1();  //  1   1 
s1();  //  1   1
s1();  //  9   1
s1();  //  9   18
s2();  //  10  18
s2();  //  10  180
s2();  //  183 180
回归主题,交替执行bar和foo
var s1 = step(foo);
var s2 = step(bar);s2();  // b--  ,yield
s2();  // yield 8
s1();  // a++, yield
s2();  // a = 8 + b, yield 2
s1();  // b= b * a,  yield b
s1();  // a = b + 3
s2();  // b = a * 2
可以看到,bar 和foo 都经过了多次的停止与启动,且它们之间进行了交替操作.
 参考《你不知道的JavaScript》(中卷)P241~P242