欢迎访问 生活随笔!

生活随笔

当前位置: 首页 > 前端技术 > javascript >内容正文

javascript

一个很简短的 JS 生成器入门和用法参考

发布时间:2025/4/5 javascript 57 豆豆
生活随笔 收集整理的这篇文章主要介绍了 一个很简短的 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 其具备下列方法:

  • next(inputValue?): { value, done }
    • (从头,或者从上次停止的位置)开始运行生成器函数体,直到遇到 yield 或者 return
    • 注意:此函数可以有一个可选的参数 inputValue 。可以在继续运行生成器函数前,为上次停顿所在的 yield 表达式设置一个值。
  • throw(e): { value, done }
    • 如果生成器函数没开始运行,则等同于原地 throw
    • 否则,在生成器函数体当前 yield 停顿的位置 throw 一个异常,然后继续运行,直到遇到 yield 、 return 或者未被捕获的异常(见下文)
  • return(value): {value, done}
    • 强行终止(即使生成器函数还没运行完毕),并指定一个 value 作为返回值
  • [Symbol.iterator]()
    • 用于迭代协议的。效果同直接调用 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 生成器入门和用法参考的全部内容,希望文章能够帮你解决所遇到的问题。

    如果觉得生活随笔网站内容还不错,欢迎将生活随笔推荐给好友。