资讯专栏INFORMATION COLUMN

切图崽的自我修养-[ES6] 生成器Generator浅析

李义 / 2748人阅读

摘要:搞这么神秘其实就是个迭代器的核心实际上就是一个,通过关键字能够把函数体拆成完全可控执行片段,在函数体外部通过来对这些执行片段进行遍历这和遍历这些数据结构是一个道理只不过用来遍历函数片段,而用来遍历元素对生成器执行操作,进行生成器的入口开始执

Generator

搞这么神秘 其实就是个迭代器

Generator的核心实际上就是一个Iterator,通过yield关键字能够把函数体拆成完全可控执行片段,在函数体外部通过next来对这些执行片段进行遍历. 这和遍历array,set,map这些数据结构是一个道理.只不过generator用来遍历函数片段,而array/set/map 用来遍历元素.

对生成器执行next()操作,进行生成器的入口开始执行代码

执行到第一个yield时,向调用者返回一个值,并将函数挂起;

挂起时,函数当前的执行上下文环境和参数被保存下来;

执行到第二个yield时,参数从挂起状态被重新调用,进入上次挂起的执行上下文环境继续下面的操作,到下一个yield操作时重复上面的过程


执行过程解析
    function *generator() {
      console.log(1);
      var x = (yield 2) +3
      console.log(3);
        var y = yield 4;
    }

    var g = generator(); 
    console.log(g.next());
    console.log(g.next());
    console.log(g.next());
    console.log(g.next());
    

var g = generator() 这一句毛都不会输出,实际上这句话执行完之后,generator()形成了内存泄漏状态,因为函数体内部的对象被外部全局变量(g)所引用,导致generator()无法被回收. 这一句执行完后实际上 g = {next:function(){xxxxxx}},

第一个g.next()会执行console.log(1),向下执行到yield关键字,将{value:2,done:false}返回給外部,然后挂起当前函数

第二个g.next()会执行 (yield 2)+3 的操作,会执行把 (yield 2)+3 赋值給x的操作, 会执行console.log(3)的操作,向下执行到yield关键字,把{value:4,done:false}返回给外部,挂起当前函数.

第三个g.next()会执行把(yield 4)赋值給y的操作,向下扫描执行,没有发现有yield或者return了,这时候会throw一个stopIterator的异常,表示在这之后已经没有yield或者return语句可以迭代了,于是把done值置为true. 返回{value:undefined,done:true}

第四个g.next()同理,返回{value:undefined,done:true}


    function *generator(z) {
      console.log(1);
      var x = (yield 2) +z
      console.log(x);
      console.log(3);
        var y = yield 4;
        console.log(y)
    }

    var g = generator(5); 
    console.log(g.next(7)); 
    console.log(g.next(8));
    console.log(g.next(9));
    console.log(g.next(10));
    

var g = generator(5)这一句毛都不输出,实际上这句话执行完之后,generator()形成了内存泄漏状态,因为函数体内部的对象被外部全局变量(g)所引用,导致generator()无法被回收. 这一句执行完后实际上 g = {next:function(){xxxxxx}}, 且函数体内的z参数被初始化成5.

第一个g.next(7)进入函数,会执行console.log(1),向下执行扫描到了yield关键字,于是将{value:2,done:false}返回給外部,然后挂起当前函数

第二个g.next(8)从上次挂起的地方进入函数,会执行 把next的参数8赋值給(yield 2)的操作, 会执行 (yield 2)+z 的操作, 会执行 把(yield 2)+z的结果赋值給x的操作, 会执行console.log(x)的操作,会执行console.log(3)的操作,继续向下执行扫描到了yield关键字,于是将{value:4,done:false}返回給外部,然后挂起当前函数

第三个g.next(9)从上次挂起的地方进入函数,会执行把next的参数9赋值給(yield 4)操作,会执行把(yield 4)赋值給y的操作,会执行console.log(y)的操作. 然后把向下执行扫描,没有发现有yield或者return了,这时候会throw一个stopIterator的异常,表示在这之后已经没有yield或者return语句可以迭代了,于是把done值置为true. 返回{value:undefined,done:true},然后挂起当前函数

第四个g.next(10)从上次挂起的地方进入函数,也是同理,返回{value:undefined,done:true},然后挂起当前函数


相关参考

由于Iterator/Generator无一例外的都涉及到了javascript函数从创建到执行到销毁的过程, 涉及到了 执行上下文EC/活动对象AO/变量对象VO/内存泄漏/回收机制 等核心概念,东西多且较复杂,有兴趣的同学可以参考汤姆大叔深入理解JavasSript系列, 里面有对javascript的核心(函数/原型链)等做了详尽的介绍.

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/50037.html

相关文章

  • 切图崽的自我修养-[ES6] 成器Generator浅析

    摘要:搞这么神秘其实就是个迭代器的核心实际上就是一个,通过关键字能够把函数体拆成完全可控执行片段,在函数体外部通过来对这些执行片段进行遍历这和遍历这些数据结构是一个道理只不过用来遍历函数片段,而用来遍历元素对生成器执行操作,进行生成器的入口开始执 Generator 搞这么神秘 其实就是个迭代器 Generator的核心实际上就是一个Iterator,通过yield关键字能够把函数体拆成完全...

    Dogee 评论0 收藏0
  • 切图崽的自我修养-[ES6] 成器Generator浅析

    摘要:搞这么神秘其实就是个迭代器的核心实际上就是一个,通过关键字能够把函数体拆成完全可控执行片段,在函数体外部通过来对这些执行片段进行遍历这和遍历这些数据结构是一个道理只不过用来遍历函数片段,而用来遍历元素对生成器执行操作,进行生成器的入口开始执 Generator 搞这么神秘 其实就是个迭代器 Generator的核心实际上就是一个Iterator,通过yield关键字能够把函数体拆成完全...

    mj 评论0 收藏0
  • 切图崽的自我修养-[ES6] 迭代器Iterator浅析

    摘要:任何数据结构只要部署接口,就可以完成遍历操作即依次处理该数据结构的成员。的遍历某个数据结构过程是这样的比如对进行遍历创建一个指针对象,指向当前数组的起始位置。 Iterator 这真是毅种循环 Iterator不是array,也不是set,不是map, 它不是一个实体,而是一种访问机制,是一个用来访问某个对象的接口规范,为各种不同的数据结构提供统一的访问机制。任何数据结构只要部署Ite...

    neu 评论0 收藏0
  • 切图崽的自我修养-[ES6] 迭代器Iterator浅析

    摘要:任何数据结构只要部署接口,就可以完成遍历操作即依次处理该数据结构的成员。的遍历某个数据结构过程是这样的比如对进行遍历创建一个指针对象,指向当前数组的起始位置。 Iterator 这真是毅种循环 Iterator不是array,也不是set,不是map, 它不是一个实体,而是一种访问机制,是一个用来访问某个对象的接口规范,为各种不同的数据结构提供统一的访问机制。任何数据结构只要部署Ite...

    springDevBird 评论0 收藏0
  • 切图崽的自我修养-[ES6] 迭代器Iterator浅析

    摘要:任何数据结构只要部署接口,就可以完成遍历操作即依次处理该数据结构的成员。的遍历某个数据结构过程是这样的比如对进行遍历创建一个指针对象,指向当前数组的起始位置。 Iterator 这真是毅种循环 Iterator不是array,也不是set,不是map, 它不是一个实体,而是一种访问机制,是一个用来访问某个对象的接口规范,为各种不同的数据结构提供统一的访问机制。任何数据结构只要部署Ite...

    happyfish 评论0 收藏0

发表评论

0条评论

李义

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<