ES6 的 Generator (生成器)

Generator 是 ES6 标准中引入的一个新的数据类型。

例子

先看看具体怎么使用

1
2
3
4
5
6
7
8
9
10
11
function* demo(i) {
yield i++;
yield i++;
return i++;
}

var de = demo(1);

de.next(); // {value: 1, done: false}
de.next(); // {value: 2, done: false}
de.next(); // {value: 3, done: true}

从上面代码可以看出:

1. Generator 和 函数 很像。
2. Generator 定义 function* 比 函数 多出一个 * 号。
3. Generator 调用后返回的结果 (迭代器对象) 需要赋值给一个变量
4. Generator 返回的结果可以多次调用。

其实上面的代码就是定义了一个以 demo 命名的 Generator (生成器)。

调用后会返回一个对象,这个对象我们称它为 迭代器。

每次调用这个返回的 迭代器 的 next 方法后,会执行第一条 yield (委托)。

并在这里暂停 (退出并保留上下文,下次进入时继续向下运行),

然后返回一个对象,这个对象包含 一个 value (yield 后面的运算结果) 和 一个 done (迭代器是否完成)

根据上面的执行结果可以看出,每调用一次 next,都会执行一次 yield。

当遇到 return 时,返回对象的 done 就变成了 true, 此时就退出了 Generator。

next 方法

1
2
3
4
5
6
7
8
9
10
11
12

function* demo() {
let i = yield 'one';
return i;
}


var de = demo();

let obj = de.next(); // {value: "one", done: false}

de.next("test:" + obj.value); // {value: "test:one", done: true}

next 方法是可以传递参数的,这个参数将作为 上次暂停的 yield 的返回值。

yield*

yield 我们知道是怎么一回事了,那 yield* 又是什么?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
function* demo() {
yield 'one';
yield foo();
yield 'four';
}

function* foo() {
yield 'two';
yield 'three';
}

var de = demo();

de.next(); // {value: "one", done: false}
de.next(); // {value: foo, done: false}
de.next(); // {value: "four", done: false}
de.next(); // {value: undefined, done: true}

调用一个 demo 生成器,执行完第一条 yield ‘one’ 后 第二条 yield foo() 调用另一个生成器。

结果发现 yield foo() 并没有去调用 foo() 生成器 中的 yield ‘two’

这是因为 yield 只会返回右边运算的值,而 foo() 返回的是一个 迭代器,所以这里的 value 会是 foo

1
2
3
// foo() 返回一个 迭代器

foo(); // foo {<suspended>}

我们改用 yield* 再试试

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
function* demo() {
yield 'one';
yield* foo();
yield 'four';
}

function* foo() {
yield 'two';
yield 'three';
}

var de = demo();

de.next(); // {value: "one", done: false}
de.next(); // {value: "two", done: false}
de.next(); // {value: "three", done: false}
de.next(); // {value: "four", done: false}
de.next(); // {value: undefined, done: true}

很多人用 Generator 来处理异步编程,但它的本质是其实是协程,下一次我们再具体说明。

关于如何使用 Generator 来处理异步编程,请看我的另一篇文章:

未完待续…

-------------本文结束感谢您的阅读-------------