Generator 函数的特性
- Generator 函数是一个状态机,封装了多个内部状态。
- Generator 函数拥有一个遍历器对象生成函数,通过遍历器对象,可以依次遍历 Generator 函数内部的每一个状态。
- Generator 函数的函数体有两个特征。一是,function关键字与函数名之间有一个星号;二是,函数体内部使用yield表达式,定义不同的内部状态(yield在英语里的意思就是“产出”)。
下面是一段Demo,
function * printUsername() {
yield "Sursyy";
yield "YY";
return "a bu";
}
var print = printUsername();
console.log(`${JSON.stringify(print.next())}`); // {"value": Spursyy, "done": false}
console.log(`${JSON.stringify(print.next())}`); // {"value": YY, "done": false}
console.log(`${JSON.stringify(print.next())}`); // {"value": a bu, "done": true}
yield 表达式
Generator 返回的是遍历器对象,每次调用next()就会遍历下一个内部状态,直至结束。
调用next()后程序执行的流程如下:
next() 的参数
generator 函数对象在执行yield 暂停后调用next() 恢复执行,这时generator函数的上下文并没有发生变化,但是我们可以通过next函数改变回复执行后的上下文
function * calculate(x) {
var y = yield 2 * (x + 1);
var z = yield y + 3;
}
var result = calculate(3);
console.log(`${JSON.stringify(result.next())}`); // {"value":8,"done":false}
console.log(`${JSON.stringify(result.next(17))}`); // {"value":20,"done":false}
yield* 表达式
如果在 Generator 函数内部,调用另一个 Generator 函数,默认情况下是没有效果的,这时就需要使用yield * 表达式。
function * classB() {
yield "zhangSan";
yield "liSi";
}
function *printName() {
yield "Spursyy";
yield * classB();
yield "YY";
}
for (let v of printName()){
console.log(v);
}
Generator.prototype.throw()
generator 函数体内还是generator 函数体外出现exception, 都可以被外部的try--catch 组合抓到。
var g = function* () {
yield
throw Error('inner error')
}
var i = g()
i.next()
try {
i.throw('exception A')
// i.next()
} catch(e) {
console.log(`error log is ${e}`);
}
Generator.prototype.return()
return() 函数有两种传递方式, 一种是在generator函数体内,另一种是通过generator 调用时传参,无论哪一种情况generator 函数体都会自行终止。
var g = function * () {
yield 1;
yield 2;
return 3;
yield 4;
}
var f = g();
console.log(`${JSON.stringify(f.next())}`); // {'value': 1, 'done': false}
console.log(`${JSON.stringify(f.next())}`); // {'value': 2, 'done': false}
console.log(`${JSON.stringify(f.next())}`); // {'value': 3, 'done': true}
console.log(`${JSON.stringify(f.next())}`); // {'done': true}
var g = function * () {
yield 1;
yield 2;
yield 3;
yield 4;
}
var f = g();
console.log(`${JSON.stringify(f.next())}`); //{'value': 1, 'done': false}
console.log(`${JSON.stringify(f.return(6))}`); //{'value': 6, 'done': false}
console.log(`${JSON.stringify(f.next())}`); //{'done': false}