生成器 Generator

在新的 ES 標(biāo)準(zhǔn)中侣姆,生成器(Generator) 幾乎是一個(gè)完全嶄新的函數(shù)類型夜郁,它能生成一組值得序列,但每個(gè)值的生成是基于每次請求卿闹,并不同于標(biāo)準(zhǔn)函數(shù)那樣立即生成揭糕。

這樣特殊的性質(zhì)萝快,也使得它成為了我們解決 JS 異步編程的一個(gè)利器。

生成器的遍歷

要遍歷生成器很簡單著角,只需要用for...of函數(shù)就可以取出每一步從生成器中返回的值揪漩。舉個(gè)例子:

function* AnimalGenerator() {
    yield 'dog';
    yield 'cat';
    yield 'fish';
}

for(let animal of AnimalGenerator()) {
    console.log(animal);
}
// => dog cat fish

生成器嵌套

生成器嵌套的方式,可以將一個(gè)生成器委托給另外一個(gè)生成器吏口,在執(zhí)行到某個(gè)節(jié)點(diǎn)的時(shí)候奄容,返回該生成器中的值:

function* AllGenerator() {
    yield 'human';
    yield* AnimalGenerator();
    yield 'AI';
}

for(let item of AllGenerator()) {
    console.log(item);
}
// => human dog cat fish AI

迭代器

在調(diào)用生成器之后,會(huì)創(chuàng)建一個(gè) 迭代器(Iterator) 并返回出來产徊,而利用迭代器就可以逐步返回生成器中的值:

const animalIterator = AnimalGenerator();

const animal1 = animalIterator.next();
const animal2 = animalIterator.next();
const animal3 = animalIterator.next();
const animal4 = animalIterator.next();

console.log(animal1, animal2, animal3, animal4);
// => {value: "dog", done: false} {value: "cat", done: false} {value: "fish", done: false} {value: undefined, done: true}

在每次執(zhí)行迭代器next方法的時(shí)候昂勒,返回一個(gè)對(duì)象,對(duì)象包含兩個(gè)屬性:

  • value:生成器的返回值舟铜,生成結(jié)束之后返回undefined;
  • done:表示生成器是否生成完畢戈盈,返回falsetrue

除此之外谆刨,迭代器的next還可以接收一個(gè)參數(shù)作為上一次yield的返回值:

function* Next(x) {
    const y = 3 * yield (x + 1);
    const z = yield (y / 10);
    yield (x + y + z);
}

const next = Next(1);

const result1 = next(); 
// => value: 2
const result2 = next(10); 
// => value: 3
const result3 = next(12); 
// => value: 43

這結(jié)果看起來有點(diǎn)繞塘娶,但是捋一捋就會(huì)發(fā)現(xiàn)很有意思:

  • 第一次調(diào)用next,返回值是第一個(gè)yield痊夭,因此就是x+1刁岸,即2
  • 第二次調(diào)用next(10)她我,傳入的值替代了第一個(gè)yield的返回值虹曙,所以y的值為3*10,即30鸦难,返回第二個(gè)yield就是30/10根吁,即3
  • 第三次調(diào)用next(12)合蔽,傳入的值替代了第二個(gè)yield,所以z的返回值為12介返,加上之前生成器緩存的x=1y=30拴事,最終返回x+y+z的值就是43

生命周期

看了這些生成器的基本用法圣蝎,肯定會(huì)對(duì)它的內(nèi)部原理很好奇刃宵。概括一下,就是直接調(diào)用一個(gè)生成器不會(huì)直接執(zhí)行徘公,而是會(huì)創(chuàng)建一個(gè)新的迭代器返回出來牲证,通過迭代器我們才能對(duì)其進(jìn)行求值。生成器每生成一個(gè)值都會(huì)自己掛起執(zhí)行关面,然后等待下一個(gè)請求坦袍。

在某種當(dāng)面來說十厢,生成器的工作更像是一個(gè)在狀態(tài)中運(yùn)動(dòng)的狀態(tài)機(jī)。

生成器生命周期

如上圖所示捂齐,生成器的生命周期主要分為四個(gè)階段:

  • Start:創(chuàng)建一個(gè)生成器以后蛮放,不執(zhí)行任何代碼,然后掛起奠宜;
  • Exucuting:執(zhí)行生成器的代碼包颁,通過迭代器的next方法調(diào)用,只要還有可執(zhí)行代碼压真,生成器都會(huì)進(jìn)入這個(gè)狀態(tài)娩嚼;
  • Yield:生成器每執(zhí)行一次,都到yield表達(dá)式處包裹一個(gè)對(duì)象返回滴肿,然后掛起等待執(zhí)行待锈;
  • Completed:如果代碼全部執(zhí)行完畢,或者遇到return嘴高,就執(zhí)行完畢竿音。

從生命周期我們可以看到,在整個(gè)周期里拴驮,只要我們?nèi)〉蒙善鞯目刂茩?quán)春瞬,它的執(zhí)行上下文就會(huì)一直保存,而不會(huì)想標(biāo)準(zhǔn)函數(shù)一樣退出后就銷毀套啤。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末宽气,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子潜沦,更是在濱河造成了極大的恐慌萄涯,老刑警劉巖,帶你破解...
    沈念sama閱讀 219,589評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件唆鸡,死亡現(xiàn)場離奇詭異涝影,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)争占,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,615評(píng)論 3 396
  • 文/潘曉璐 我一進(jìn)店門燃逻,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人臂痕,你說我怎么就攤上這事伯襟。” “怎么了握童?”我有些...
    開封第一講書人閱讀 165,933評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵姆怪,是天一觀的道長。 經(jīng)常有香客問我,道長稽揭,這世上最難降的妖魔是什么俺附? 我笑而不...
    開封第一講書人閱讀 58,976評(píng)論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮淀衣,結(jié)果婚禮上昙读,老公的妹妹穿的比我還像新娘。我一直安慰自己膨桥,他們只是感情好蛮浑,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,999評(píng)論 6 393
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著只嚣,像睡著了一般沮稚。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上册舞,一...
    開封第一講書人閱讀 51,775評(píng)論 1 307
  • 那天蕴掏,我揣著相機(jī)與錄音,去河邊找鬼调鲸。 笑死盛杰,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的藐石。 我是一名探鬼主播即供,決...
    沈念sama閱讀 40,474評(píng)論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼于微!你這毒婦竟也來了逗嫡?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,359評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤株依,失蹤者是張志新(化名)和其女友劉穎驱证,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體恋腕,經(jīng)...
    沈念sama閱讀 45,854評(píng)論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡抹锄,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,007評(píng)論 3 338
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了吗坚。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片祈远。...
    茶點(diǎn)故事閱讀 40,146評(píng)論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖商源,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情谋减,我是刑警寧澤牡彻,帶...
    沈念sama閱讀 35,826評(píng)論 5 346
  • 正文 年R本政府宣布,位于F島的核電站,受9級(jí)特大地震影響庄吼,放射性物質(zhì)發(fā)生泄漏缎除。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,484評(píng)論 3 331
  • 文/蒙蒙 一总寻、第九天 我趴在偏房一處隱蔽的房頂上張望器罐。 院中可真熱鬧,春花似錦渐行、人聲如沸轰坊。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,029評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽肴沫。三九已至,卻和暖如春蕴忆,著一層夾襖步出監(jiān)牢的瞬間颤芬,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,153評(píng)論 1 272
  • 我被黑心中介騙來泰國打工套鹅, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留站蝠,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,420評(píng)論 3 373
  • 正文 我出身青樓卓鹿,卻偏偏與公主長得像菱魔,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子减牺,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,107評(píng)論 2 356

推薦閱讀更多精彩內(nèi)容