1.含義
??Generator 和普通函數(shù)不同,可以將它看成是封裝了很多狀態(tài)的函數(shù)月趟,每執(zhí)行一次該函數(shù)槐瑞,就會返回一個(gè)遍歷器對象,該遍歷對象可以遍歷Generator函數(shù)中的每一個(gè)狀態(tài)颊埃。
2.特征
① 命名:在函數(shù)名前面加個(gè)星號
② 定義狀態(tài)
??使用yield表達(dá)式,每一個(gè)yield定義的表達(dá)式就是Generator函數(shù)的一個(gè)狀態(tài)
③ 執(zhí)行
??通過普通函數(shù)調(diào)用的形式調(diào)用Generator函數(shù)蝶俱,并不會執(zhí)行,而是返回一個(gè)生成器對象實(shí)例饥漫,只有調(diào)用了實(shí)例中的next()方法才會執(zhí)行內(nèi)部的代碼
④ 返回結(jié)果
??并不是一個(gè)具體的數(shù)據(jù)榨呆,而是一個(gè)執(zhí)行內(nèi)部狀態(tài)的指針對象
function* helloWorldGenerator() {
yield 'hello';
yield 'world';
return 'ending';
}
var hw = helloWorldGenerator();
hw.next(); //{value:'hello',done:'false'}
hw.next(); //{value:'world',done:'false'}
hw.next(); //{value:'ending',done:'false'}
hw.next(); //{value:'undefined',done:'ture'}
??上述代碼中,共有三個(gè)狀態(tài) 'hello'庸队、'world'积蜻、'ending'闯割。 通過函數(shù)調(diào)用的形式將helloWorldGenerator的一個(gè)生成器對象實(shí)例賦值到 hw中。然后通過hw實(shí)例的next方法執(zhí)行函數(shù)內(nèi)的代碼竿拆,具體的執(zhí)行步驟如下:
??第一次調(diào)用next方法宙拉,遍歷對象的指針從函數(shù)頭部往下移動,開始執(zhí)行函數(shù)內(nèi)的代碼丙笋,遇到第一個(gè)yield谢澈,暫停函數(shù)的執(zhí)行,此時(shí)next()方法返回一個(gè)對象: {value:'hello',done:'false'}御板。value的值就是yield表達(dá)式的值锥忿,done的值為false,表示函數(shù)并沒有執(zhí)行完畢怠肋;
??第二次調(diào)用next方法敬鬓,遍歷對象的指針從第一個(gè)yield表達(dá)式的地方開始往下移動,直到遇到第二個(gè)yield笙各,停止函數(shù)的執(zhí)行钉答,同樣,此時(shí)next方法也返回一個(gè)對象:{value:'world',done:'false'};
??第三次調(diào)用next方法杈抢,遍歷對象的指針從第二個(gè)yield表達(dá)式的大方開始往下移動数尿,直到遇到return關(guān)鍵字,終止函數(shù)的執(zhí)行春感,此時(shí)next方法也返回一個(gè)對象: {value:'ending',done:'true'}砌创;
??第四次調(diào)用next方法,遍歷對象的指針在第三步已經(jīng)指向了該函數(shù)的結(jié)尾鲫懒,表示函數(shù)已經(jīng)執(zhí)行完畢嫩实,此時(shí)的next方法也返回一個(gè)對象:{value:'undefined',done:'true'}.不管后面調(diào)用多少次的next方法,只要遇到了return關(guān)鍵字或者已經(jīng)執(zhí)行到函數(shù)的末尾窥岩,value值就為undefined甲献,done值都為true。
3.yield
??Generator函數(shù)相當(dāng)于是分段執(zhí)行的颂翼,而yield相當(dāng)于一個(gè)暫停標(biāo)記晃洒,只要遇到一個(gè)yield表達(dá)式,函數(shù)就會暫停執(zhí)行朦乏,直到調(diào)用了next方法球及,當(dāng)調(diào)用了next()方法,yield后面的表達(dá)式才會被執(zhí)行呻疹。
function* gen() {
yield 123 + 456;
}
??上述代碼中吃引,123 + 456 不會立即求值,直到調(diào)用了next()方法才會求值。
??另外镊尺,yield表達(dá)式如果用在另一個(gè)表達(dá)式之中朦佩,必須放在圓括號里面。
function* gen() {
consoloe.log('hello' + yield world) //Error
consoloe.log('hello' + (yield world)) //right
}
??yield表達(dá)式用作函數(shù)參數(shù)或放在賦值表達(dá)式的右邊庐氮,可以不加括號语稠。
function* gen(a) {
gen(yield 1);
let b = yield 4;
}
4.next 執(zhí)行邏輯
??首先明確,執(zhí)行完next()方法就不返回一個(gè)對象: {value:'',done:''}弄砍。value的值就是yield或者return 后面的值仙畦,done的值為Boolean,表示該函數(shù)是否遍歷完畢输枯,具體的執(zhí)行邏輯如下:
??① 首次調(diào)用next()方法议泵,遍歷對象的指針就從函數(shù)頭部往下偏移,開始執(zhí)行函數(shù)內(nèi)部的代碼桃熄,直到遇到第一個(gè)yield表達(dá)式就停止函數(shù)的執(zhí)行先口,并返回一個(gè)獨(dú)對象;
??② 當(dāng)?shù)诙握{(diào)用next()方法時(shí)瞳收,遍歷對象的指針就從第一個(gè)yield表達(dá)式的位置往下偏移碉京,執(zhí)行函數(shù)內(nèi)的代碼, 直到遇到下一個(gè)yield表達(dá)式螟深;
??③ 如果沒有新的yield表達(dá)式谐宙,就一直運(yùn)行到函數(shù)結(jié)束,直到遇到return語句就終止函數(shù)的進(jìn)行界弧,并將return關(guān)鍵字后面的值做為value值凡蜻;
??④ 如果該函數(shù)沒有return語句,就將value置為undefined垢箕。