【细读JS忍者秘籍】深入生成器函数的底层原理

本文深入探讨JavaScript生成器函数的底层原理,分析执行上下文的生成与迭代器对象的交互。当执行生成器函数时,其执行上下文并不会立即执行,而是创建一个迭代器并返回。通过next方法,可以恢复生成器函数的执行,参数作为yield语句的返回值。生成器函数的执行上下文始终保持唯一,通过迭代器在挂起和恢复之间切换,实现非堵塞执行。

深入生成器函数的底层原理

分析执行上下文

生成器函数本质上还是一个_函数_,所以它的执行离不开 执行上下文

function* generator() {console.log("status1");yield "hello";console.log("status2");yield "world";}

let gen = generator();
let one = gen.next(); 

1. 我们试着分析在执行gen = generator() 这句代码前的执行上下文状态:

此时执行上下文栈(后面统称ECS) 中的_栈顶_是 全局执行上下文

该上下文中, 全局对象(window) 上保存了 generator 函数对象。

gen , one 是 let 声明所以在 词法环境中_未进行初始化_

2. 当执行 gen = generator() 时 , 创建 generator 函数的执行上下文:

此时,ECS的_栈顶_是 生成器函数 generator 的执行上下文

从这个时刻开始,就体现出 function *function 的_区别_:

generator 的执行上下文生成好以后,

_不会_和常规的函数一样,开始执行代码。

而是会_创建_一个 指向 generator 执行上下文的 迭代器 并_返回该对象_

注意:

  • 这里并_没有执行_生成器函数内部的代码
  • 生成好执行上下文后,创建了一个指向该上下文环境的对象(被称作_迭代器_)然后返回

和正常的函数一样,生成器函数的上下文被弹出栈顶 (这也是不堵塞挂起的原因)

但由于上下文环境生成的对象_没有失去引用_,因此被保留了下来(和_闭包_一个原理)

执行next 方法

执行 next 方法时,也很_特殊_:

  • 不会_创建 next 方法的上下文,而是将迭代器中保存的_生成器函数的上下文_重新激活_压入栈顶,并从上次挂起的 yeild 位置开始_继续_执行代码。* 从这里可以看出,这就是 生成器函数_不会堵塞_执行的原因,因为_只有执行 next 函数时_,生成器函数的上下文才会被压入栈顶。每次执行到 yeild 关键字就让next返回结果,并_弹出栈顶挂起_,_等待_下次激活。> 你是否还记得 next() 方法的参数?

我们可以在执行 next 方法时传入参数。

该参数很奇怪,会作为_上一次yeild语句的返回值_。

刚开始我会觉得这种设计很奇怪,但是现在看来这是一种很_正常_的逻辑:

我们执行 next 时,将生成器函数从_挂起_状态_恢复_到执行状态。

next方法的_参数_,为这次的_恢复执行_提供了一个_信息_,该信息保存在 上次挂起(这次恢复) 的语句,也就是作为上次yeild语句的返回值

我们通过yeild语句从生成器中_得到_返回值,再使用迭代器的 next 方法把值_传回_生成器,实现了双向通信。

普通函数每次调用都会_创建_一个新的执行上下文,而生成器函数_不同_,自始至终都是使用_一个上下文_,而这个上下文对象由于_被迭代器引用_,所以_不会_被当作垃圾从内存中回收掉。

普通函数的执行上下文只有调用时才新创建,相比之下,生成器函数的上下文会_暂时挂起并在将来恢复_。

总结:

  • 执行生成器函数后,不执行其中的代码,而是_返回一个保存了其上下文对象的迭代器。* 每次调用迭代器的 next 方法,不会_创建 next 方法的上下文,而是_将迭代器中保存的生成器的上下文重新激活压入栈顶。* next 方法的参数作为_上次挂起的语句的返回值。

最后

最近找到一个VUE的文档,它将VUE的各个知识点进行了总结,整理成了《Vue 开发必须知道的36个技巧》。内容比较详实,对各个知识点的讲解也十分到位。



有需要的小伙伴,可以点击下方卡片领取,无偿分享

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值