ES6 Generator 生成器介绍

发布于 2022-01-17 23:24:49 字数 4634 浏览 1007 评论 0

Generator 是 ES6 引入的实现异步操作的一种新方法,在 Generator 出现之前,不管哪种方法,异步操作都是使用回调函数来实现的。只从出现了 Generator 之后,开发人员可以使用同步调用的逻辑来实现异步操作,只要在需要等待的地方,使用 yield 语句放弃运行即可。

Generator 的基本写法

和学习所有其他语言特性一样,我们使用一个 Hello World 来作为 Generator 的入门代码

function* helloworld(){
    yield "Hello";
    return "World!";
}

func = helloworld();
func.next();//return { value: 'Hello', done: false }
func.next();//return { value: 'World!', done: true }
func.next();//return { value: '', done: true }

从上面的代码的输出可以看出

  • Generator 函数的定义,是通过 function * 实现的
  • 对 Generator 函数的调用返回的实际是一个遍历器,随后代码通过使用遍历器的next方法来获得函数的输出
  • 通过使用 yield 语句来中断 Generator 函数的运行,并且可以返回一个中间结果
  • 每次调用 next 方法,Generator 函数将执行到下一个yield语句或者是return语句。下面我们就对上面代码的每次next调用进行一个详细的解释
    • 第一次调用 next 方法的时候,函数执行到 yield "Hello" 语句停了下来,并且返回了 Hello 这个 value,随同value返回的done属性表明Generator 函数的运行还没有结束
    • 第二次调用 next 方法的时候,函数执行到 return "World!" 语句停了下来,并且返回了 World! 这个 value,随同 value 返回的done属性表明 Generator 函数的运行已经结束
    • 第三次调用 next 方法的时候,由于 Generator 函数执行已经结束了,所以函数调用立即返回,done 属性表明 Generator 函数已经结束运行,value 是空的,因为这次调用并没有执行任何语句

yield 语句

yield 语句在 Generator 函数的执行过程中扮演了中断/暂停执行函数的功能。每次你调用 next() 方法的时候,Generator 函数都将执行到下一个 yield 语句或者 return 语句,当执行到 yield 语句的时候,如果 yield 语句跟着一个表达式,那么表达式的值将作为 value 被返回。

next 方法参数

由于 yield 语句只是抛出 value,但是本身并不返回 value,如果你要 yield 语句有返回值,就要在调用 next 方法的时候,传入一个参数,这个参数就将作为上一个 yield 语句的返回值,下面是一个例子

function* f() {
  for(var i=0; true; i++) {
    var reset = yield i;
    if(reset) { i = -1; }
  }
}

var g = f();

g.next() // { value: 0, done: false }
g.next() // { value: 1, done: false }
g.next(true) // { value: 0, done: false }

for...of 循环

在上面的所有例子中,如果我们要让 Generator 函数执行下一步,就必须调用一次 next 方法,那么有没有什么方法让 Generator 函数自动执行每一步而不需要代码干预呢?答案是肯定的,我们可以使用 for...of 循环来实现,下面是一个具体的例子。在下面的例子中,for..of loop 将遍历所有的 yield语句(记住只是遍历 yield 语句,因此 return 语句的返回值是不会输出的

function* loopThroughInt(){
    for (let index = 0; index < 100; index++){
        yield index;
    }
    return 100;
}
for (let v of loopThroughInt()){
    console.log(v); //output 0...99
}

yield*

如果在 Generator 函数内部需要调用另外一个 Generator 函数,那么对目标函数的调用就需要使用 yield*,以下是一个简单的例子

function* objects(){
    yield "cat";
    yield "dog";
    yield "duck";
}
function* say(){
    yield* objects();
    yield " say hello world!";
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据

关于作者

JSmiles

生命进入颠沛而奔忙的本质状态,并将以不断告别和相遇的陈旧方式继续下去。

0 文章
0 评论
84960 人气
更多

推荐作者

沧笙踏歌

文章 0 评论 0

山田美奈子

文章 0 评论 0

佚名

文章 0 评论 0

岁月无声

文章 0 评论 0

暗藏城府

文章 0 评论 0

    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文