发布于 

生成器generator

生成器执行例子

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
//构造生成器函数
var a = 1;
var b = 2;

functionfoo() {
a++;
yield;
b = b * a;
a = (yield b) + 3;
}

functionbar() {
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() {
// 不管yield出来的是什么,下一次都把它原样传回去!
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(); // b--;
s2(); // yield 8
s1(); // a++;
s2(); // a = 8 + b;
// yield 2
s1(); // b = b * a;
// yield b
s1(); // a = b + 3;
s2(); // b = a * 2;

以上代码执行推导

**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 {
//for...of循环需要
[Symbol.iterator]:function(){return this},
//标准迭代器接口方法
next:function(){
if(nextVal===undefined){
nextVal=1
}else{
nextVal = (3 * nextVal)+6
}
return {done:false,value:nextVal} //done表示迭代状态,value为迭代值
}
}
})()

//进行迭代
for (var v of something) { //for..of循环期望something是iterable,于是它寻找并调用它的 //Symbol.iterator函数。
console.log( v );

// 不要死循环!
if (v > 500) {
break;
}
}
// 1 9 33105 321969

通过生成器实现上面的例子

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
        functionsomething() {
var nextVal;

while (true) {
if (nextVal === undefined) {
nextVal = 1;
}
else {
nextVal = (3 * nextVal) + 6;
}

yield nextVal;
}
}

//for...of循环
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)
}