ES6中的生成器和迭代器

生成器函数generator function 用function *name () {}来声明,调用生成器函数则会返回一个生成器对象generator,并且符合可迭代协议和迭代器协议,因此generator也是一个迭代器对象,具有next()方法,调用next()方法会执行生成器函数内的语句(即遍历生成器函数内部的状态,状态值由yield后的表达式值给出)。

function *foo ( x ) {
	yield 1;
	var y = x + ( yield 2 );
	var z = y + ( yield );
	return; 
}
var it = foo(3); // x = 3; 首次调用生成器函数返回一个对象,具有next()方法的迭代器对象;
it.next().value; // 1 ;调用next方法来遍历状态,在遇到yield语句时停下来,返回具有{value: value, done: false}形式的对象,其中value值是yield后的表达式值,done表示迭代是否结束;
it.next().value; // 2 第二次调用next方法,从上次yield停下来的地方继续执行,注意上一次只执行yield及其表达式,如果yield表达式包含在语句中,则该语句不会执行,直到再次被启动;
it.next(4).value; // undefined;  y = 7; 第三次调用next方法时传入一个值,yield表达式可以接收值,也可以生成值,生成的值会被next方法返回,接受的值由next方法传入作为整个yield表达式的值,所以此时y = 3 + 4; 然后继续执行到下一个yield处(var z = y + (yield) ),由于yield后没有值,所以生成值为undefined;
it.next(5).value; // undefined; z = 12; 第四次调用next方法传入5,可以得到z = 7 + 5; 执行到return结束,返回对象为{value: undefined, done: true};

每次调用生成器函数构建迭代器时,同时隐式构建了生成器实例,迭代器对应执行的是新的生成器实例,因此可以构建多个迭代器来控制对应生成器实例,互相之间并不会干扰。比如

function *bar () {
	yield 1;
	yield 2;
	return;
}
var it1 = bar();
var it2 = bar();
it1.next(); // {value: 1, done: false}
it2.next(); // {value: 1, done: false},并非{value: 2, done: false}

利用生成器实例的暂停执行机制,可以控制多个生成器函数交替执行,如果这些函数有共享的变量,则可以模仿多线程竞态条件环境。
for of遍历方法
典型的for of遍历写法for (let v of something),其中something是迭代器对象,或者具有[Symbol.iterator]属性的对象,如数组,Map集合和Set集合,而v则是迭代器对象调用next方法返回对象的value属性值;for of结构中迭代器对象自动调用next方法,直到返回对象的done属性值为true;
如果生成器函数内部有无限多个状态,如

function *foo () {
	var nextVal;
	while (true) {
		if (nextVal === undefined ) {
			nextVal = 1;
		} else {
			nextVal = 2 * nextVal;
		}
		yield nextVal;
	}
}

利用for ( let v of foo())则会一直无限循环下去,那么如何让生成器停止呢?

给for of添加break、return语句;for of结构在遇到break、return或者有异常时,并非会挂起状态,而是会向迭代器对象发送一个信号使其终止;break和return会触发运行生成器内部的finally语句;

var it = foo();
for ( let v of it ) {
	console.log(v);
	if ( v > 500 ) {
		break; // 或者用return
		// it.return('done!'); 迭代器对象调用return方法来发出终止信号,并且设置返回对象为{value: 'done', done: true};
	}
}

注意:在可迭代对象(如数组,Map和Set集合)中,迭代对象并没有return方法,只有next方法,这一点跟生成器函数返回的迭代对象有区别;如

var arr = [1, 2, 500, 600,3, 4];
var it = arr[Symbol.iterator]();
for(let v of it) {
    console.log(v);
    if(v > 500) {
        it.return('done!');
    }
}
1 
2 
500 
600 
TypeError: it.return is not a function
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值