Generator神秘莫测,其实就是一个迭代器。Generator的核心其实就是一个Iterator。可以通过yield关键字将函数体拆分成完全可控的执行片段,这些执行片段可以在函数体外部通过next遍历。这和遍历array、set、map等数据结构是一样的。只不过generator是用来遍历函数片段的,而array/set/map是用来遍历元素的。对generator执行next()操作,执行generator的entry开始执行代码,当执行到第一个yield时,返回一个值给caller,函数被挂起;函数挂起时,保存函数当前执行上下文和参数;当第二次yield执行时,参数从挂起状态被重新调用,进入上次挂起的执行上下文继续后面的操作,对下一个yield操作重复上述过程执行过程parsingfunction*generator(){控制台日志(1);varx=(yield2)+3console.log(3);变量y=产量4;}varg=generator();console.log(g.next());console.log(g.next());console.log(g.next());console.log(g.next());varg=generator()这句话不会输出,实际上这句话执行完后,generator()形成了内存泄漏状态,因为函数体内的对象被外部全局变量(g)引用,generator()不能回收。这句话执行完后,g={next:function(){xxxxxx}},第一个g.next()会执行console.log(1),往下执行到yield关键字,return{value:2,done:false}到外部,然后暂停当前函数。第二个g.next()会执行(yield2)+3的操作,会执行将(yield2)+3赋值给x的操作,会执行console.log(3)的操作,一直到yield关键字,{value:4,done:false}返回到外部并挂起当前函数。第三个g.next()将执行(yield4)向下扫描执行给y赋值的操作,没有找到yield或return。这时候会抛出stopIterator异常,说明后面没有yield或者return语句可以迭代,所以设置done值为true。return{value:undefined,done:true}第四个g.next()同理,return{value:undefined,done:true}function*generator(z){console.log(1);varx=(yield2)+zconsole.log(x);控制台日志(3);变量y=产量4;console.log(y)}varg=generator(5);console.log(g.next(7));console.log(g.next(8));console.log(g.next(9));console.log(g.next(10));varg=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赋值给(yield2)的操作,会执行(yield2)+z的操作,该操作将(yield2)+z的结果赋值给x,会执行console.log(x)的操作,会执行console.log(3)操作,继续往下扫描到yield关键字,然后return{value:4,done:false}到外面,然后挂起当前函数的第三个g.next(9)从上次暂停的地方进入函数,执行下一个参数9赋值给(yield4)的操作,执行把(yield4)赋值给y的操作,将执行console.log(y)操作。然后向下扫描,发现没有yield或return。这时候会抛出stopIterator异常,说明后面没有yield或者return语句可以迭代,所以设置done值为true。返回{value:undefined,done:true},然后挂起当前函数。第四个g.next(10)从上次挂起的地方进入函数。同理,return{value:undefined,done:true},然后暂停当前函数的相关参考由于Iterator/Generator无一例外地涉及到javascript函数从创建到执行再到销毁的过程,涉及核心概念如executioncontextEC/activeobjectAO/variableobjectVO/memoryleak/recyclingmechanism,东西比较多也比较复杂,有兴趣的同学可以参考汤姆大叔深入理解JavasScript系列,里面有对核心的详细介绍javascript(函数/原型链)等。
