生成器generator
生成器执行例子
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| 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); }
|
1 2 3 4 5 6 7 8 9 10
| function step(gen) { var it = gen(); var last;
return function() { last = it.next( last ).value; }; }
|
1 2 3 4 5 6 7 8 9 10 11 12 13
| var s1 = step( foo ); var s2 = step( bar );
s2(); s2(); s1(); s2(); s1(); s1(); s2();
|
以上代码执行推导
**var s1 = step( foo )**:s1为一个函数,it为生成器函数foo()
**var s2 = step( bar )**:s2为一个函数,it为生成器函数bar()
第一次**s2()**:bar函数启动,执行b–,b的值为1后停止执行,此时的yield返回undefined,last为undefined
第二次**s2()**:bar函数继续往下执行,遇到yield 8 停止 ,yield返回8 ,last为8
第一次**s1()**:foo函数启动,a的值为2后停止执行,此时的yield返回undefined,last为undefined
第三次执行**s2()**:(yield 8)被传进来last替代,a为9,b = 9 * (yield 2)后停止执行,此时yield返回2,last为2
第二次**s1()**:b = 9,a=(yield b)后停止执行,此时yield将b返回,所以last为9
第三次**s1()**:(yield b)被传进来的last替代,所以a = 12
第四次**s2()*:(yield 2)被传进来的last替代,所以b=92,b=18
迭代器接口
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
| var something = (function(){ var nextVal; return { [Symbol.iterator]:function(){return this}, next:function(){ if(nextVal===undefined){ nextVal=1 }else{ nextVal = (3 * nextVal)+6 } return {done:false,value:nextVal} } } })()
for (var v of something) { console.log( v );
if (v > 500) { break; } }
|
通过生成器实现上面的例子
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| function *something() { var nextVal;
while (true) { if (nextVal === undefined) { nextVal = 1; } else { nextVal = (3 * nextVal) + 6; }
yield nextVal; } }
for (var v of something()) { console.log( v );
if (v > 500) { break; } }
|
问题:在实现迭代器接口时,for…of是这样使用:for (var v of something),用生成器实现时却是这样:for (var v of something())
生成器实现数组遍历
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| var array = [10,99,50,-1]
function *arrGen(array){ var arr = array; var nextVal; var i = 0;
while(true){ if(i<arr.length){ nextVal = arr[i] }else{ return 'end' } i++ yield nextVal; }
} for(let v of arrGen(array)){ console.log(v) }
|
生成器实现对象遍历
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
| var person = { name: 'zhangs', age: 18, sex: 'male' }
function* objGen(person) { var obj = person; var nextVal; var i = 0; var propertyList = Object.keys(obj)
while (true) { if (i < propertyList.length) { nextVal = {} var proName = propertyList[i] nextVal[proName] = obj[propertyList[i]] }else{ return 'end' } i++; yield nextVal } }
for(let v of objGen(person)){ console.log(v) }
|