generator(生成器)小结

初遇

生成器函数,顾名思义,生成对象,生成一个遍历器。

function* generator(){
    yield 0;
    yield 1;
    yield 2;
}

let iterator = generator();

iterator.next();    //{value:0,done:false}
iterator.next();    //{value:1,done:false}
iterator.next();    //{value:2,done:false}
iterator.next();    //{value:undefined,done:true}
  • generator()为生成器函数,在function函数名之间添加*表明该函数为生成器函数。
  • generaotor()调用返回一个遍历器,赋值给iterator
  • iterator有多个方法,next()return()throw()
  • 通过yield和上述三个方法控制生成器函数代码块的执行。

yield和next( )

  • 生成器代码不会自动执行,多个yield将代码分成多个部分,等待信号才会执行,信号就是上述遍历器的几个方法。
  • 调用next()时生成器代码执行,执行完含yield语句时停止。下一次调用next()时,继续执行。
  • next()的返回值为一个对象:{value:"",done:false},该对象包含valuedone字段。
  • value值为本次执行代码中yield其后表达式的值。done的值为true或者false,表示当前遍历器是否执行完毕。
  • 上述代码执行情况
    1.第一个next()启动生成器执行,执行完yield 0后停止,next()返回值为{value:0,done:false}
    2.第二个next()调用,生成器继续执行,执行完yield 1后停止,next()返回值为{value:1,done:false}
    3.第三次next()调用和第二次相似,next()返回值为{value:2,done:false}
    4.第四次next()调用时,生成器已执行完毕,value字段值默认值undefined,done字段值为true。后续调用都是如此。

    yield语句返回值、next( )参数

    • yield语句默认为值为undefined
    function* generator () {
          const data0 = yield 0;
          console.log(data0);         //打印出值为undefined
    
          const data1 = yield 1;     
          console.log(data1);         //打印出值为undefined
    
          const data2 = yield 2;     
          console.log(data2);         //打印出值为undefined
      }
    
      let iterator = generator();
    
      iterator.next();
      iterator.next();
      iterator.next();
      iterator.next();
      //yield语句默认值为undefined,data0、data1、data2所赋到的值为undefined
    
    • 通过向next()传入参数改变上个yield语句的返回值。
      function* generator () {
          const data0 = yield 1;
          console.log(data0);         //打印出值为"data0"
    
          const data1 = yield 1;     
          console.log(data1);         //打印出值为"data1"
    
          const data2 = yield 2;     
          console.log(data2);         //打印出值为"data2"
      }
    
      let iterator = generator();
    
      iterator.next();
      iterator.next("data0");
      iterator.next("data1");
      iterator.next("data2");
    

return( )

这样一段代码,生成器中含return语句。遍历器刚好结束遍历时,value字段默认值为undefined,return返回的值会赋给当前next()返回值的value字段。即代码块中第三次next()调用。

  function* generator(){
      yield 0;
      yield 1;
      return 2;
  }
  
  let iterator = generator();
  
  console.log(iterator.next());    //{value:0,done:false}
  console.log(iterator.next());    //{value:1,done:false}
  console.log(iterator.next());    //{value:2,done:true}
  console.log(iterator.next());    //{value:undefined,done:true}

遍历器的return()

遍历器的next()表示继续向后执行,return则表示直接返回,结束执行。

  function* generator() {
      yield 0;
      yield 1;
      yield 2;
  }

  let iterator = generator();
  console.log(iterator.next());
  console.log(iterator.return());
  • 上述代码执行完yield 0后停止,return()被调用,提前结束遍历。后续yield 1yield 2不会被执行。
  • return()返回值默认为{value:undefined,done:true}value字段值可由return()的参数设置,同next()

throw( )

  • 所生成遍历器也有自己的throw(),会优先触发生成器内部的try-catch
function* generator() {
       try {
           const data = yield;
       } catch(e) {
           console.log("内部检测到",e.message);
       }
   }
   let iterator = generator();
   iterator.next();
   iterator.throw(new Error("error"))
  • 内部无try-catch时,触发外部try-catch
  • 多次 throw()时,第一次由内部捕获,后续由外部捕获。

底层原理

  • 基于协程的实现。
  • 单个线程上可有多个协程,线程控制权可交由不同的协程控制,每个时间点只能由一个协程控制。
  • 运行生成器函数时创建新的协程,所创建它的协程的称为父协程。
  • 开始时由父协程控制,调用next()时,将线程控制权交由生成器协程,遇到yeild时将控制权交回父协程。
  • 每个协程在转交控制权前都会保存自己的调用栈,方便再次执行。
    本文只是浮光掠影,更多细节内容请前往阮一峰ES6
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,922评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,591评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,546评论 0 350
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,467评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,553评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,580评论 1 293
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,588评论 3 414
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,334评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,780评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,092评论 2 330
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,270评论 1 344
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,925评论 5 338
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,573评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,194评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,437评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,154评论 2 366
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,127评论 2 352

推荐阅读更多精彩内容