Generator 函數(shù)的特性
- Generator 函數(shù)是一個狀態(tài)機巫玻,封裝了多個內(nèi)部狀態(tài)丛忆。
- Generator 函數(shù)擁有一個遍歷器對象生成函數(shù),通過遍歷器對象仍秤,可以依次遍歷 Generator 函數(shù)內(nèi)部的每一個狀態(tài)熄诡。
- Generator 函數(shù)的函數(shù)體有兩個特征。一是诗力,function關(guān)鍵字與函數(shù)名之間有一個星號凰浮;二是,函數(shù)體內(nèi)部使用yield表達(dá)式苇本,定義不同的內(nèi)部狀態(tài)(yield在英語里的意思就是“產(chǎn)出”)袜茧。
下面是一段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 表達(dá)式
Generator 返回的是遍歷器對象瓣窄,每次調(diào)用next()就會遍歷下一個內(nèi)部狀態(tài)惫周,直至結(jié)束。
調(diào)用next()后程序執(zhí)行的流程如下:
generateor流程.jpg
next() 的參數(shù)
generator 函數(shù)對象在執(zhí)行yield 暫停后調(diào)用next() 恢復(fù)執(zhí)行康栈,這時generator函數(shù)的上下文并沒有發(fā)生變化递递,但是我們可以通過next函數(shù)改變回復(fù)執(zhí)行后的上下文
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* 表達(dá)式
如果在 Generator 函數(shù)內(nèi)部,調(diào)用另一個 Generator 函數(shù)啥么,默認(rèn)情況下是沒有效果的登舞,這時就需要使用yield * 表達(dá)式。
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 函數(shù)體內(nèi)還是generator 函數(shù)體外出現(xiàn)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() 函數(shù)有兩種傳遞方式, 一種是在generator函數(shù)體內(nèi)氯迂,另一種是通過generator 調(diào)用時傳參践叠,無論哪一種情況generator 函數(shù)體都會自行終止。
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}