生成器函数
generator(生成器)是 ES6 标准引入的新的数据类型。一个 generator 看上去像一个函数,但可以返回多次。
generator 函数和普通的函数区别有两个, 1:function 和函数名之间有一个*号, 2:函数体内部使用了 yield 表达式
创建生成器对象
调用 生成器函数 和调用 普通函数不同,调用生成器函数是返回一个 生成器对象(可迭代的对象)
// * 和 yield
function* gen() {
yield "1";
yield 2;
}
let iter = gen(); // 创建生成器对象 iter(可迭代)
生成器对象的使用方法
-
next()
调用 生成器对象的 next() 方法,才是真正开始执行生成器函数,每次遇到 yield 或者 return 就会返回一个对象{value: "1", done: false}
value 表示 yield 或 return 后面的值。
done 表示这个 对象是否已经结束(迭代到末尾了) -
forof 循环
调用迭代器循环 生成器对象。可以直接获取到 yield 后面的值。 -
扩展运算符
...生成器对象 也可以获取 yield 后面的值。
【注 1】next()到 return 表示结束(没有 return,其实是隐含了 return undefined),且 return 之后的 yield 不会被执行到
【注 2】done 到最后返回 true,表示结束
【注 3】return 不会被 forof 和扩展运算符遍历到。所以只能用 next()获取到 return 的值
function* gen() {
yield "1";
yield 2;
yield 3;
yield 4;
return 5;
}
let iter = gen();
console.log(iter.next()); // {value: "1", done: false}
for (const i of iter) {
console.log(i); // 从 2 开始,到 4 结束。不会获得return的值
}
console.log(...iter); //不用上面的forof,用扩展运算符得出的结果 和上面是一样的
yield*
委托,可以委托给其他生成器或者可迭代对象。
//其他生成器
function* g1() {
yield 2;
yield 3;
yield 4;
}
function* g2() {
yield 1;
yield* g1();
yield 5;
}
var iterator = g2();
console.log(iterator.next()); // { value: 1, done: false }
console.log(iterator.next()); // { value: 2, done: false }
console.log(iterator.next()); // { value: 3, done: false }
console.log(iterator.next()); // { value: 4, done: false }
console.log(iterator.next()); // { value: 5, done: false }
console.log(iterator.next()); // { value: undefined, done: true }
// 可迭代对象
function* g3() {
yield* [1, 2];
yield* "34";
yield* arguments;
}
var iterator = g3(5, 6);
console.log(iterator.next()); // { value: 1, done: false }
console.log(iterator.next()); // { value: 2, done: false }
console.log(iterator.next()); // { value: "3", done: false }
console.log(iterator.next()); // { value: "4", done: false }
console.log(iterator.next()); // { value: 5, done: false }
console.log(iterator.next()); // { value: 6, done: false }
console.log(iterator.next()); // { value: undefined, done: true }
next 的参数
如果给 next 方法传参数, 那么这个参数将会作为上一次 yield 语句的返回值 ,这个特性在异步处理中是非常重要的, 因为在执行异步代码以后, 有时候需要上一个异步的结果, 作为下次异步的参数
function* foo(x) {
var y = 2 * (yield x + 1);
var z = yield y / 3;
return x + y + z;
}
var a = foo(5);
console.log(a.next()); // 6
console.log(a.next()); // NaN,由于这次next没带参数,相当于上一个x+1为undefined,所以 y == 2 * undefined == NaN
console.log(a.next()); // NaN
var b = foo(5);
console.log(b.next()); // 6
console.log(b.next(12)); // 8
console.log(b.next(13)); // 42