《你不知道的JavaScript》:生成器函数执行模式初体会

在js中,有一个普遍依赖的假定:一个函数一旦开始执行,就会运行到结束,期间不会有其他代码能够打断它并插入其间。

但ES6中引入了一个新的函数类型,它并不符合这种运行到结束的特性。这类新的函数被称为生成器

看下面的普通函数示例:

var x = 1;
function foo(){
    x++;
    bar();
    console.log(x);
}
function bar(){
    x++;
}
foo();      // 3

上例中,bar()会在foo()函数中执行,导致foo()函数执行后x值为3。但如果bar()不在foo函数中,最后的显示结果就是2,而不是3。

那可以想个问题,如果bar()不在那儿,但出于某种原因要它仍然可以在x++console.log(x);语句之间运行,该怎么实现呢?

此时就可以使用ES6的生成器来实现这样的功能:

var x = 1;
function *foo(){
    x++;
    yield;
    console.log(x);
}
function bar(){
    x++;
}

// 构造一个迭代器it来控制生成器*foo()
var it = foo();

//这里启动  *foo()生成器
it.next();
console.log(x);     // 2
bar();
console.log(x);     // 3
it.next();

首先注意上例中的生成器格式 function *foo(){},通常这个*号位置还有其他两种,它们都是等价的:function* foo(){}function*foo(){}。而这里采用第一种格式是因为使用*foo(){}来引用生成器时会比较一致,如果只是foo()的形式,就不容易搞清指的是生成器还是常规函数。所以这只是一种风格偏好。

现在在描述下上例的运行过程:

  • var it = foo();运算并没有执行生成器 *foo(),而只是构造了一个迭代器(iterator),这个迭代器会控制它的执行。
  • 第一个it.next();启动了生成器*foo(),并运行了*foo()第一行的代码x++
  • *foo()yield语句处暂停,在这个点位上第一个it.next()调用结束。此时*foo()仍然是运行且活跃的,但函数处理暂停状态。
  • 此时查看x的值,是2
  • 然后调用bar(),它通过x++两次递增x的值
  • 此时再次查看x的值,它变成了3
  • 最后的it.next()调用从暂停处恢复了生成器*foo()的执行,并运行console.log()语句,这条语句使用当前x的值3。

所以可以这样理解:foo()启动了,但是没有完整运行,它在yield处暂停了。暂停其间可以执行其他需要的代码,执行完后再调用迭代器it的next()方法恢复生成器foo()并让它继续执行到结束。

所以生成器就是一类特殊的函数,可以一次或多次启动和停止,并不一定非得到完成。

它将用于构建以生成器作为异步流程控制的代码模式的基础构件之一。

喜欢本文请扫下方二维码,关注微信公众号: 前端小二,查看更多我写的文章哦,多谢支持。
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值