生成器
生成器(Generators): 一个更好的方法来构建遍历器。 --- 生成器和迭代器
生成器就是一类特殊的函数,特殊之处在于:
- 字面量(函数声明/函数表达式)的关键字function后面多了一个
*
,而且这个*
前后允许有空白字符,如:
function* foo(){}
function *foo(){}
function*foo(){}
- 函数体中多了
yield
运算符 - 普通函数的执行模式是: 执行-结束, 生成器的执行模式是: 执行-暂停-结束
yield语句
yield语句是Generator函数内部可以暂停执行程序的语句,yield语句后面的值可以是各种数据类型,字符串,整数,布尔值等等都可以。
看个小栗子:
function *foo() {
yield 1;
yield 'hello';
yield 'generator';
return true;
}
let f1 = foo();
f1.next(); // Object {value: 1, done: false}
f1.next(); // Object {value: "hello", done: false}
f1.next(); // Object {value: "generator", done: false}
f1.next(); // Object {value: true, done: true}
f1.next(); // Object {value: undefined, done: true}
这个例子反映了生成器的基本用法,有以下几点值得注意:
- 在调用foo()时,函数体中的逻辑并不会执行(控制台没有输出),直接调用f1.next()时才会执行
- f1是一个对象,它由生成器foo()调用而来,注意foo()并没有返回f1对象
- 调用f1.next()时,函数体中的逻辑才开始真正执行,每次调用时会到yield语句结束,并将yield的运算数作为结果返回
- f1.next()返回的结果是一个对象,对yield的运算数做了包装,并带上了done属性
- 当done属性为false时,表示该函数逻辑还未执行完,可以调用f1.next()继续执行
- 当返回的结果为return语句返回的结果,且done值为true
- 返回值中done为true时,仍然可以继续调用,返回的值为undefined
yield和return
看个栗子:
function *bar() {
yield 1;
yield 'hello';
return true;
yield 'generator';
}
let b1 = bar();
b1.next(); // Object {value: 1, done: false}
b1.next(); // Object {value: "hello", done: false}
b1.next(); // Object {value: true, done: true}
b1.next(); // Object {value: undefined, done: true}
从上面例子可以看出,当碰到return语句时,返回对象的done属性值就为true,遍历结束,不管后面是否还有yield或者return语句。不管是普通函数还是Generator函数,一旦遇到return语句,便不再返回新的值。
yield 和 yield*
在生成器中,yield* 可以把需要 yield 的值委托给另外一个生成器或者其他任意的可迭代对象。
function* gen1() {
yield 2;
yield 3;
yield 4;
}
function* gen2() {
yield 1;
yield* gen1();
yield 5;
}
var g = gen2();
g.next(); // Object { value: 1, done: false }
g.next(); // Object { value: 2, done: false }
g.next(); // Object { value: 3, done: false }
g.next(); // Object { value: 4, done: false }
g.next(); // Object { value: 5, done: false }
g.next(); // Object { value: undefined, done: true }
网友评论