es6-generator
前言
在各路文档中,了解到 Generator 是一个生成器,目的是为了生成一个 Iterator -- "迭代器",用以进行流程控制,让代码在你需要停止的地方提下来,并能够在下次流程进行的时候在上次停止的地方开始。
其中有几个重要的名次及其概念列举如下:
Generator其译为生成器,目的是为了通过其创建一个迭代器,声明方法如下👇;function * generatorFun(){} // 或 function* generatorFun(){} // 或 function *generatorFun(){} // 或 function* generatorFun(){}其中
*的位置并没有强制限制,只要保证在function与生成器名称之间就可以了。next()为获取迭代器执行结果的方法,主要用法如下:function * generatorFun(){ yield 1; }; const gf = generatorFun(); gf.next(); // { value:1, done: false }需要注意的是,直接调用
generatorFun,并不能像常规函数那样直接获取函数执行结果,而是获得了一个迭代器Iterator,在找到的一些文章中,大多愿意称其为指向函数内部状态的指针对象,当调用迭代器对象内的next方法时,其指针便会从函数头部或上一次停下来的地方继续执行;yield其译为产出,产出的是其后面的表达式的运行结果,然后在yield处暂停执行,直到下次调用next方法触发才会在停止处继续执行,且当yield用在表达式中时,需要放在圆括号里,如下,:function* demo() { console.log('Hello' + yield); // SyntaxError console.log('Hello' + yield 'world'); // SyntaxError console.log('Hello' + (yield)); // OK console.log('Hello' + (yield 'world')); // OK }
基本用法
从上述描述中基本可以了解到 Generator 的基本用法如下👇图所示。
其中有这么几个需要注意的点[1]:
如上图中的代码,即使只有一个
yield,当第一次调用gf.next()也并没有直接到done的状态,这其实比较好理解,因为第一次的next并没有使代码运行到函数尾部,而是停留在了yield上,尽管yield之后再无可执行代码;生成器函数执行流程区别于普通函数,举个🌰: 从上图可以看到,普通函数与生成器函数的执行顺序主要区别在于
yield表达式使得每一次调用next最终都会将函数暂停在yield表达式或者函数尾部,直到下次调用next将从上一个yield运行到下一个yield或者函数尾部。从上图的生成函数代码中会发现一个问题,就是最后的输出结果是
NaN,这其实是因为yield只负责“产出”导致的,也就是yield表达式并不能将它右侧的表达式运行结果返回到左侧,而如果需要上一步的结果,则可以借助next来进行传参,如下:
进阶
for of
for of for of 循环可以自动遍历 Generator 函数时生成的 Iterator 对象,且此时不再需要调用 next 方法。如下:
通过观察输出结果,我们发现一个问题,就是最后的 javascript 并没有输出出来,这是因为 for of 循环在 done === true 时便中止掉了,并且不会返回当前结果,所以最后的 return 结果并没有获取到。
除了 for...of 循环以外,扩展运算符(...)、解构赋值和 Array.from[2] 方法内部调用的,都是遍历器接口。这意味着,它们都可以将 Generator 函数返回的 Iterator 对象,作为参数。[3]
Generator.prototype.throw()
Generator.prototype.throw()一个在生成器函数外部向函数体内部抛出错误的方法。
Generator.prototype.return()
Generator.prototype.return() 一个在生成器函数外部向函数体内部 return,并终结遍历。
yield*
yield* yield* 表达式用于委托给另一个 generator 或 可迭代对象[4]。[5]
yield* 有区别于 yield。yield 可以将其理解为暂停标识符,即在 yield 处开始或停止。而 yield* 则可以理解为展开一个可迭代对象进行迭代。举个🌰:
上述代码其实可以看作等价于下面的代码
只不过有一条需要注意的是 yield_return 是我为了方便理解自己定义的一个标识,实际上是没有这个东西的。之所以这么定义是因为 yield* 所委托的迭代对象 return 的 value 将作为返回值返回到 yield* 表达式上,再举个🌰:
参考资料:
[2]. Array.from
[3]. ES6中的Generator函数
[4]. JS 可迭代对象
[5]. yield*
[6]. Markdown syntax
以上描述及解决方案均属个人观点,若您存在任何疑问及意见,还请联系本人 ✉️ 邮箱。
最后更新于
这有帮助吗?