基本介绍
- Generator 函数是一个状态机,封装了多个内部状态。
- 执行 Generator 函数会返回一个遍历器对象,可以依次遍历 Generator 函数内部的每一个状态。
- function关键字与函数名之间有一个星号,函数体内部使用yield表达式,定义不同的内部状态。
function* helloWorldGenerator() {
yield 'hello';
yield 'world';
return 'ending';
}
var hw = helloWorldGenerator();
console.log(hw.next()) // { value: 'hello', done: false }
console.log(hw.next()) // { value: 'world', done: false }
console.log(hw.next()) // { value: 'ending', done: true }
console.log(hw.next()) // { value: undefined, done: true }
// value属性表示当前的内部状态的值,是yield表达式后面那个表达式的值;done属性是一个布尔值,表示是否遍历结束。
yield 表达式
- yield表达式只能用在 Generator 函数里面,用在其他地方都会报错。
- yield表达式如果用在另一个表达式之中,必须放在圆括号里面。
- 如果yield表达式后面跟的是一个遍历器对象,需要在yield表达式后面加上星号,表明它返回的是一个遍历器对象。这被称为yield*表达式。
function* foo() {
yield 'a';
yield 'b';
}
function* bar() {
yield 'x';
yield* foo();
yield 'y';
}
for (let v of bar()) {
console.log(v);
}
// x a b y
遍历器对象的方法
- next()
yield表达式本身没有返回值,或者说总是返回undefined。next方法可以带一个参数,该参数就会被当作上一个yield表达式的返回值。
由于next方法的参数表示上一个yield表达式的返回值,所以在第一次使用next方法时,传递参数是无效的。
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()) //{ value: 6, done: false }
console.log(a.next()) //{ value: NaN, done: false }
console.log(a.next()) //{ value: NaN, done: true }
var b = foo(5);
console.log(b.next()) //{ value: 6, done: false }
console.log(b.next(3)) // { value: 2, done: false }
console.log(b.next(5)) // { value: 16, done: true } x=5 y=6 z=5
- throw()
Generator 函数返回的遍历器对象,都有一个throw方法,可以在函数体外抛出错误,然后在 Generator 函数体内捕获。
throw方法可以接受一个参数,该参数会被catch语句接收,建议抛出Error对象的实例。
throw方法被捕获以后,会附带执行下一条yield表达式。也就是说,会附带执行一次next方法。
一旦 Generator 执行过程中抛出错误,且没有被内部捕获,就不会再执行下去了。
function* g() {
try {
yield;
} catch (e) {
console.log('内部捕获', e);
}
yield console.log('b');
};
var i = g();
i.next();
i.throw(new Error('出错了!')); //内部捕获 Error: 出错了! b
- return()
可以返回给定的值,并且终结遍历 Generator 函数。
如果 Generator 函数内部有try…finally代码块,那么return方法会推迟到finally代码块执行完再执行。
function* gen() {
yield 1;
yield 2;
yield 3;
}
var g = gen();
console.log(g.next()) // { value: 1, done: false }
console.log(g.return('foo')) //{ value: 'foo', done: true }
console.log(g.next()) //{ value: undefined, done: true }
- Generator 函数的this
Generator 函数返回的总是遍历器对象,而不是this对象。
Generator 函数也不能跟new命令一起用,会报错。
function* g() {
this.a = 11;
}
let obj = g();
console.log(obj.a) //undefined