Generator

1.簡單知識點(diǎn)

  • 執(zhí)行 Generator 函數(shù)會返回一個遍歷器對象

  • 每次調(diào)用next方法毡庆,內(nèi)部指針就從函數(shù)頭部或上一次停下來的地方開始執(zhí)行,直到遇到下一個yield表達(dá)式(或return語句)為止随橘。換言之,Generator 函數(shù)是分段執(zhí)行的,yield表達(dá)式是暫停執(zhí)行的標(biāo)記对嚼,而next方法可以恢復(fù)執(zhí)行。

  • yield表達(dá)式只能用在 Generator 函數(shù)里面绳慎,用在其他地方都會報錯纵竖。

  • yield表達(dá)式如果用在另一個表達(dá)式之中,必須放在圓括號里面杏愤。

  • 對象的Symbol.iterator方法即是對象的便利生成器函數(shù)靡砌。Generator生成的遍歷生成器對象也具有Symbol.iterator屬性,這個屬性返回他本身珊楼。

    function* gen(){
      // some code
    }
    var g = gen();
    g[Symbol.iterator]() === g//true
    

2.next()

  • yield表達(dá)式本身無返回值通殃。next()可以帶一個參數(shù),當(dāng)作上一個yield的返回值厕宗。
    e.g.

    function * fibonacci(){
      let [prev, curr] = [0, 1];
       for(;;){
          [prev, curr] = [curr, curr+prev];
          yield curr;
        } 
    }
    
    for(let n of fibonacci()){
         if(n>1000){
            break;
         }
         console.log(n);
    }
    

補(bǔ)充:for..of画舌,解構(gòu)賦值,Array.from()媳瞪,...擴(kuò)展運(yùn)算符調(diào)用的都是遍歷器接口骗炉。

3.throw()

throw拋出的錯誤,由try-catch語句中的catch捕獲蛇受。throw 分為外部的throw命令和生成器的throw()方法句葵。throw命令拋出的錯誤只能被函數(shù)體外捕獲。

  • 函數(shù)體外拋出異常,函數(shù)能夠捕獲乍丈。

    try{  
         g.throw("error");
     }catch(e){
         console.log(e);
    }
    

一旦 Generator 執(zhí)行過程中拋出錯誤剂碴,且沒有被內(nèi)部捕獲,就不會再執(zhí)行下去了轻专。如果此后還調(diào)用next方法忆矛,將返回一個value屬性等于undefined、done屬性等于true的對象请垛,即 JavaScript 引擎認(rèn)為這個 Generator 已經(jīng)運(yùn)行結(jié)束了催训。

同樣函數(shù)內(nèi)部拋出的錯誤,函數(shù)外部可以捕獲宗收。函數(shù)內(nèi)部有try-catch語句塊漫拭,g.throw()先被函數(shù)內(nèi)部的try-catch捕獲。當(dāng)函數(shù)內(nèi)部不存在try-catch語句塊時混稽,直接被函數(shù)外部的try-catch捕獲采驻。捕獲到函數(shù)內(nèi)部拋出的錯誤錯誤,則g.next().done為true匈勋,表示遍歷結(jié)束礼旅,不再執(zhí)行。

  • throw方法被捕獲后洽洁,會附帶執(zhí)行下一條yield表達(dá)式痘系。
  • throw命令與g.throw()無關(guān)。兩者不影響诡挂。throw命令不會影響遍歷器的狀態(tài)碎浇。

4.return()

 g.return('foo');

調(diào)用return()結(jié)束遍歷器,并返回遍歷器的返回值璃俗。
注意try-finally語句塊奴璃。調(diào)用return()后,執(zhí)行finally塊中的代碼城豁,執(zhí)行完后返回return()苟穆。
總結(jié):return(),next()唱星,throw()雳旅,都是對yield表達(dá)式的替換。next是值的替換间聊,throw()替換成throw語句攒盈,return()替換成return語句

5.關(guān)于yield

  • 在generator函數(shù)中調(diào)用generator。利用yield*
    yield * iterator對象 相當(dāng)于for...of遍歷的簡寫

  • 利用yield創(chuàng)建二叉樹

     function Tree(left, label, right) {
        this.left = left;
       this.label = label;
       this.right = right;
     }
     function make(array) {
        // 判斷是否為葉節(jié)點(diǎn)
       if (array.length == 1) return new Tree(null, array[0], null);
       return new Tree(make(array[0]), array[1], make(array[2]));
     }
     let tree = make([[['a'], 'b', ['c']], 'd', [['e'], 'f', ['g']]]);
     console.log(tree);
    
  • 利用yield遍歷二叉樹

6.generator中的this

generator不能夠和new一起用哎榴,所以就不能夠?qū)his綁定在生成器
出現(xiàn)的問題是:

  function* g() {
     this.a = 11;
  }

  let obj = g();
  obj.a // undefined

解決方法型豁,創(chuàng)建空對象僵蛛,使用call綁定generator內(nèi)部的this對象

  function* F() {
       this.a = 1;
       yield this.b = 2;
       yield this.c = 3;
    }
   var obj = {};
   var f = F.call(obj);

  f.next();  // Object {value: 2, done: false}
  f.next();  // Object {value: 3, done: false}
  f.next();  // Object {value: undefined, done: true}

  obj.a // 1
  obj.b // 2
  obj.c // 3

7.generator函數(shù)與狀態(tài)機(jī)

generator中一個yield就是一個狀態(tài)

*8.generator與協(xié)程序

  • 協(xié)程就是:一個線程(或函數(shù))執(zhí)行到一半,可以暫停執(zhí)行迎变,將執(zhí)行權(quán)交給另一個線程(或函數(shù))充尉,等到稍后收回執(zhí)行權(quán)的時候,再恢復(fù)執(zhí)行衣形。這種可以并行執(zhí)行驼侠、交換執(zhí)行權(quán)的線程(或函數(shù)),就稱為協(xié)程谆吴。
  • 協(xié)程與普通線程的區(qū)別:同一時間可以有多個線程處于運(yùn)行狀態(tài)倒源,但是運(yùn)行的協(xié)程只能有一個,其他協(xié)程都處于暫停狀態(tài)纪铺。此外相速,普通的線程是搶先式的,到底哪個線程優(yōu)先得到資源鲜锚,必須由運(yùn)行環(huán)境決定,但是協(xié)程是合作式的苫拍,執(zhí)行權(quán)由協(xié)程自己分配芜繁。

9.generator的應(yīng)用

異步同步化
利用yield,按順序執(zhí)行異步函數(shù)
多步驟管理

  • promise的方式

     Promise.resolve(step1)
       .then(step2)
       .then(step3)
       .then(step4)
       .then(function (value4) {
      // Do something with value4
      }, function (error) {
     // Handle any error from step1 through step4
     })
    .done();
    

promise.done:不會反悔promise對象绒极,因此不能夠接cache()骏令,形成promise鏈。異常直接拋出給外部垄提。作用榔袋,防止promise中的人為的,難以查找出的錯誤铡俐。

  • generator 中yield

     function* longRunningTask(value1) {
       try {
          var value2 = yield step1(value1);
          var value3 = yield step2(value2);
          var value4 = yield step3(value3);
          var value5 = yield step4(value4);
              // Do something with value4
         } catch (e) {
             // Handle any error from step1 through step4
          }
      }
    

注意:這里generator是同步化的凰兑,不存在異步調(diào)用。
部署iterator 接口

 function* iterEntries(obj) {
    let keys = Object.keys(obj);
    for (let i=0; i < keys.length; i++) {
    let key = keys[i];
    yield [key, obj[key]];
    }
}

let myObj = { foo: 3, bar: 7 };

for (let [key, value] of iterEntries(myObj)) {
       console.log(key, value);
 }

 // foo 3
 // bar 7

Object.keys()
Object.keys() 方法會返回一個由一個給定對象的自身可枚舉屬性組成的數(shù)組审丘,數(shù)組中屬性名的排列順序和使用 for...in循環(huán)遍歷該對象時返回的順序一致 (兩者的主要區(qū)別是 一個 for-in 循環(huán)還會枚舉其原型鏈上的屬性)
作為數(shù)據(jù)結(jié)構(gòu)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末吏够,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子滩报,更是在濱河造成了極大的恐慌锅知,老刑警劉巖,帶你破解...
    沈念sama閱讀 221,198評論 6 514
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件脓钾,死亡現(xiàn)場離奇詭異售睹,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)可训,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,334評論 3 398
  • 文/潘曉璐 我一進(jìn)店門昌妹,熙熙樓的掌柜王于貴愁眉苦臉地迎上來捶枢,“玉大人,你說我怎么就攤上這事捺宗≈埃” “怎么了?”我有些...
    開封第一講書人閱讀 167,643評論 0 360
  • 文/不壞的土叔 我叫張陵蚜厉,是天一觀的道長长已。 經(jīng)常有香客問我,道長昼牛,這世上最難降的妖魔是什么术瓮? 我笑而不...
    開封第一講書人閱讀 59,495評論 1 296
  • 正文 為了忘掉前任,我火速辦了婚禮贰健,結(jié)果婚禮上胞四,老公的妹妹穿的比我還像新娘。我一直安慰自己伶椿,他們只是感情好辜伟,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,502評論 6 397
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著脊另,像睡著了一般导狡。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上偎痛,一...
    開封第一講書人閱讀 52,156評論 1 308
  • 那天旱捧,我揣著相機(jī)與錄音,去河邊找鬼踩麦。 笑死枚赡,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的谓谦。 我是一名探鬼主播贫橙,決...
    沈念sama閱讀 40,743評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼茁计!你這毒婦竟也來了料皇?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,659評論 0 276
  • 序言:老撾萬榮一對情侶失蹤星压,失蹤者是張志新(化名)和其女友劉穎践剂,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體娜膘,經(jīng)...
    沈念sama閱讀 46,200評論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡逊脯,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,282評論 3 340
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了竣贪。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片军洼。...
    茶點(diǎn)故事閱讀 40,424評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡巩螃,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出匕争,到底是詐尸還是另有隱情避乏,我是刑警寧澤,帶...
    沈念sama閱讀 36,107評論 5 349
  • 正文 年R本政府宣布甘桑,位于F島的核電站拍皮,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏跑杭。R本人自食惡果不足惜铆帽,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,789評論 3 333
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望德谅。 院中可真熱鬧爹橱,春花似錦、人聲如沸窄做。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,264評論 0 23
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽椭盏。三九已至冯键,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間庸汗,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,390評論 1 271
  • 我被黑心中介騙來泰國打工手报, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留蚯舱,地道東北人。 一個月前我還...
    沈念sama閱讀 48,798評論 3 376
  • 正文 我出身青樓掩蛤,卻偏偏與公主長得像枉昏,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子揍鸟,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,435評論 2 359

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

  • 簡介 基本概念 Generator函數(shù)是ES6提供的一種異步編程解決方案兄裂,語法行為與傳統(tǒng)函數(shù)完全不同。本章詳細(xì)介紹...
    呼呼哥閱讀 1,076評論 0 4
  • 在此處先列下本篇文章的主要內(nèi)容 簡介 next方法的參數(shù) for...of循環(huán) Generator.prototy...
    醉生夢死閱讀 1,451評論 3 8
  • 官方中文版原文鏈接 感謝社區(qū)中各位的大力支持阳藻,譯者再次奉上一點(diǎn)點(diǎn)福利:阿里云產(chǎn)品券晰奖,享受所有官網(wǎng)優(yōu)惠,并抽取幸運(yùn)大...
    HetfieldJoe閱讀 6,380評論 9 19
  • 上一篇介紹了Promise異步編程腥泥,可以很好地回避回調(diào)地獄匾南。但Promise的問題是,不管什么樣的異步操作蛔外,被Pr...
    張歆琳閱讀 1,442評論 0 13
  • 哥倆今天去美院打球蛆楞,照片不知道選哪張...貼出來溯乒,找不同吧... 大雨:你看吧,我先跑了~ 奕奕: 你傻愣愣吧豹爹,我...
    大雨不愁閱讀 217評論 0 0