在编写生成器的实现代码之前,首先来介绍一下生成器。生成器是 ES6 的新特性,可以实现代码的暂停,类似于下方的代码。
function *func() {
console.log("1");
yield;
console.log("2");
}
var it = func();
it.next(); //打印 1
console.log('3'); //打印 3
it.next(); //打印 2
这段代码的输出结果是 1、3、2。在这段代码中,一共有三点需要注意的地方:
第一点是 * 符号,这是生成器的定义符号。在一个普通的函数声明中,如果函数名前方有一个 * 符号,就是定义了一个生成器。
第二点是 it = func() ,这里的 func() 的返回值是一个对象,这个对象是一个迭代器对象,用于控制生成器的暂停与执行。
第三点是 next,代码中有两个 next。第一个 next 用于使生成器开始执行,当执行到 yield 时,生成器就会暂停执行。这时需要 func() 返回的对象再调用一次 next ,生成器会继续执行直到结束或遇到下一个 yield(这段代码的生成器中只有一个 yield ,所以执行到结束)
以上是生成器的最简单的声明与使用,目前来看生成器就像一个能够暂停的函数,但生成器不止这一个功能。
生成器还可以进行一个双向的数据传递,比如像下面这样:
function *func() {
var num = yield '传出的值';
console.log(num);
}
var it = func();
var val = it.next().value;
console.log(val); //打印 '传出的值'
it.next(6); //打印 6
在这段代码中有两个值的传递:
第一个是 yield 后面的字符串,这个值通过第一个 next 后使用 value 得到。第二个是通过在调用 next 是传入一个值,这个值会代替暂停点 yield,赋值到 num。
这个地方有一个顺序需要弄清楚,第一个 next 是启动生成器,到达 yield 就会停止,所以不应该传入值。第二个 next 由 yield 开始,所以传入值会“替换”掉 yield。