聲明Generator函數(shù)
?????Generator函數(shù),又稱生成器函數(shù),是ES6的一個重要的新特性。
//聲明一個Hello的Generator函數(shù)
function* Hello(name) {
yield `hello ${name}`;
yield `how are you`;
yield `bye`;
}
?????注意:
1玷禽、普通函數(shù)用function來聲明赫段,Generator函數(shù)用function*聲明。
2矢赁、Generator函數(shù)內(nèi)部有新的關鍵字:yield糯笙,普通函數(shù)沒有。
調(diào)用Generator函數(shù)
//聲明一個Hello的Generator函數(shù)
function* Hello(name) {
yield `hello ${name}`;
yield `how are you`;
yield `bye`;
}
//調(diào)用Hello函數(shù)
let ite = Hello('王德發(fā)');
//結(jié)果:[object Generator]
ite.next();
//{value: "hello 王德發(fā)", done: false}
ite.next();
//{value: "how are you", done: false}
ite.next();
//{value: "bye", done: false}
ite.next();
//{value: undefined, done: true}
?????函數(shù)執(zhí)行后撩银,返回了一個:[object Genrator]生成器對象给涕,我們把它賦值到變量ite中,僅此而已蜒蕾,并沒有做太多的事情稠炬。
?????第1次調(diào)用生成器對象ite的next( )方法焕阿,返回了一個對象:
{value: "hello 王德發(fā)", done: false}
?????第2次調(diào)用生成器對象ite的next( )方法咪啡,同樣得到了一個對象:
{value: "how are you", done: false}
?????第3次調(diào)用生成器對象ite的next( )方法,又得到了一個對象:
{value: "bye", done: false}
?????第4次調(diào)用生成器對象ite的next( )方法暮屡,返回的對象:
{value: undefined, done: true}
Generator函數(shù)的行為
?????Generator函數(shù)被調(diào)用后并不會一直執(zhí)行到最后撤摸,它是先回返回一個生成器對象,然后hold住不動褒纲,等到生成器對象的next( )方法被調(diào)用后准夷,函數(shù)才會繼續(xù)執(zhí)行,直到遇到關鍵字yield后莺掠,又會停止執(zhí)行衫嵌,并返回一個Object對象,然后繼續(xù)等待彻秆,直到next( )再一次被調(diào)用的時候楔绞,才會繼續(xù)接著往下執(zhí)行,直到done的值為true唇兑。
yield語句的作用
?????而yield在這里起到了十分重要的作用酒朵,就相當于暫停執(zhí)行并且返回信息。有點像傳統(tǒng)函數(shù)的return的作用扎附,但不同的是普通函數(shù)只能return一次蔫耽,但是Generator函數(shù)可以有很多個yield。而return代表的是終止執(zhí)行留夜,yield代表的是暫停執(zhí)行匙铡,后續(xù)通過調(diào)用生成器的next( )方法,可以恢復執(zhí)行碍粥。
next( )方法接收參數(shù)
?????next( )方法還可以接受一個參數(shù)鳖眼,它的參數(shù)會作為上一個yield的返回值,我們來看一下:
//聲明一個Hello的Generator函數(shù)
function* Hello() {
let res = yield `hello`;
yield res;
}
let iterator = Hello();
//結(jié)果:一個生成器對象
iterator.next();
//結(jié)果:{value: "hello", done: false}
iterator.next("王德發(fā)");
//結(jié)果:{value: "王德發(fā)", done: false}
?????注意函數(shù)體內(nèi)的第一個yield關鍵字即纲,我們把它的返回值賦值給了一個變量res具帮。
?????再看2次next方法的調(diào)用:
?????第1次調(diào)用next( )方法博肋,返回的對象屬性value值為“hello”,屬性done值為:fasle蜂厅,并暫停執(zhí)行匪凡。
?????第2次next( )方法,傳入?yún)?shù):字符串“王德發(fā)”掘猿。此時病游,第二個yield關鍵字緊跟著的是變量res,而變量res的值正是上一個關鍵字yield的返回值稠通。也就是說這個值正是我們傳入的參數(shù):“王德發(fā)”衬衬。因為:next( )的參數(shù)會作為上一個yield的返回值。
關鍵字yield*
?????在一個Generator函數(shù)里面改橘,如果我們想調(diào)用另一個Generator函數(shù)滋尉,就需要用到的關鍵字是:yield*。
//聲明Generator函數(shù):gen1
function* gen1() {
yield "gen1 start";
yield "gen1 end";
}
//聲明Generator函數(shù):gen2
function* gen2() {
yield "gen2 start";
yield "gen2 end";
}
//聲明Generator函數(shù):start
function* start() {
yield "start";
yield* gen1();
yield* gen2();
yield "end";
}
//調(diào)用start函數(shù)
var ite = start();
//創(chuàng)建一個生成器
ite.next();
//{value: "start", done: false}
ite.next();
//{value: "gen1 start", done: false}
ite.next();
//{value: "gen1 end", done: false}
ite.next();
//{value: "gen2 start", done: false}
ite.next();
//{value: "gen2 end", done: false}
ite.next();
//{value: "end", done: false}
?????我們主要看start( )這個Generator函數(shù)飞主,其中有兩句代碼:
yield* gen1();
yield* gen2();
????? 如果一個Generator函數(shù)A執(zhí)行過程中狮惜,進入(調(diào)用)了另一個Generator函數(shù)B,那么會一直等到Generator函數(shù)B全部執(zhí)行完畢后碌识,才會返回Generator函數(shù)A繼續(xù)執(zhí)行碾篡。
Generator函數(shù)的用途
????? 它可以控制函數(shù)的內(nèi)部狀態(tài),依次遍歷每個狀態(tài)筏餐;可以根據(jù)需要开泽,輕松地讓函數(shù)暫停執(zhí)行或者繼續(xù)執(zhí)行。利用Generator函數(shù)暫停執(zhí)行的作用魁瞪,可以將異步操作的語句寫到y(tǒng)ield后面穆律,通過執(zhí)行next方法進行回調(diào)。