javascript
一个很简短的 JS 生成器入门和用法参考
生成器函数
在写其他 js 代码时会经常用到 debugger 的东西,能够让当前运行的函数暂停住。生成器函数里的 yield 关键词也能使得函数暂停运行,同时还能用来做数据的输入输出(如果是 debugger,只能手动去逐个 inspect 变量)。
yield 可以当作“断点”。yield value 除了能当作断点,还可以向外部输出 value。
此外,yield 表达式本身也是可以有值的,也就是说还可以表示外部传入的数据。只要外部在调用 next(inputValue) 时输入一个值。 这就是为什么在赋值语句里,可以用 yield 作为右值(例如,在使用了 react-saga 的项目里到处都是这种玩意儿)。
function* fn1(){var data = yield "字符串反转器已启动"yield data.split("").reverse().join("") }// 创建 Generator 对象 var g = fn1()// 运行函数,直到遇到第一个“断点”(yield 处) console.log(g.next())// 上次停顿的位置是 var data = yield "字符串反转器已启动" // 因此可以在继续运行前,使得 (yield "字符串反转器已启动") 的值为 "Hello" console.log(g.next("Hello")) // 输出: // { value: '字符串反转器已启动', done: false } // { value: 'olleH', done: false } 复制代码Generator
正如前面的示例,调用一个 function* 生成器函数,会返回一个 Generator 对象(上文的 g)。这个对象是可迭代对象(最常见的用法,即用于 for of 循环中)。
此外,可以把它当作一个控制器,控制着一个被 yield 打了断点(而且还没开始运行)的函数。
Generator 其具备下列方法:
- (从头,或者从上次停止的位置)开始运行生成器函数体,直到遇到 yield 或者 return
- 注意:此函数可以有一个可选的参数 inputValue 。可以在继续运行生成器函数前,为上次停顿所在的 yield 表达式设置一个值。
- 如果生成器函数没开始运行,则等同于原地 throw
- 否则,在生成器函数体当前 yield 停顿的位置 throw 一个异常,然后继续运行,直到遇到 yield 、 return 或者未被捕获的异常(见下文)
- 强行终止(即使生成器函数还没运行完毕),并指定一个 value 作为返回值
- 用于迭代协议的。效果同直接调用 next()
yield*
和 yield 关键词相比,多了一个星号。可以把 yield* another_iterable 当作以下代码语法糖:
for (let item of another_iterable) {yield item; } 复制代码也就是说,在生成器函数里, yield* 就是针对一个可迭代对象,把它的每一项逐个地 yield 出来。
有趣的例子:
- yield* [1,2,3] 会把3个数字逐个 yield 出来。数组是可迭代的。
- yield* "abcdefg" 会把这7个字母逐个 yield 出来。字符串也是可迭代对象。
- yield* another_generator 相当于把另一个 Generator 的输出,当作自己的输出给一个个 yield 出去了。
- 这个有趣的特性可以用来做拦截器之类的应用。
- 说到了串联,如果是当前生成器函数想要利用另外一个生成器的返回值,直接调用 another_generator.next().value 就行了
生成器函数内的异常
由 next() 或者 throw(e) 可以让生成器函数开始运行。在运行过程中,如果生成器函数里遇到了未被捕获的异常(可以是生成器内部自己产生的,或者由外部调用 throw(e) 塞进去的),那么会在外部由 next() 或者 throw(e) 给 throw 出来
function* test(){try {console.log("inner: Hello")console.log("inner: GET" + (yield "output1"))} catch (err) {console.log("inner: Caught", err)}console.log("inner: Done")return "output 2" }var g = test() console.log("outer: next: ", g.next("input 1")) console.log("outer: throw: ", g.throw("err")) console.log("outer: next: ", g.next("input 2")) 复制代码上面的例子输出如下。注意到由外部提供的 input1 不会被输出,因为那是生成器函数还没开始运行的时候传进去的,能传到哪里?没有任何的意义。
inner: Hello outer: next: { value: 'output1', done: false } inner: Caught err inner: Done outer: throw: { value: 'output 2', done: true } outer: next: { value: undefined, done: true } 复制代码安利
写了一个 Markdown 编辑器组件,只要一个框,所见即所得,而且还全面兼容 CodeMirror(一个很强大的代码编辑组件)
悄悄安利一下: laobubu.net/HyperMD/
(欢迎来 GitHub 点赞 或者帮我买杯咖啡)
总结
以上是生活随笔为你收集整理的一个很简短的 JS 生成器入门和用法参考的全部内容,希望文章能够帮你解决所遇到的问题。
- 上一篇: HashMap的容量(桶的数量)为什么要
- 下一篇: SpringBoot集成Redis--配