JavaScript 引擎实现 ECMAScript 2017 (ES8) 的 Generator yield* 表达式的分析

阅读时长 5 分钟读完

Generator 是 ECMAScript 6 新增的一种函数形式,使用 yield 关键字可以暂停函数的执行并返回一个值,下次执行时从上次暂停的位置继续。在 ES8 中,还新增了 yield* 表达式,可以用来在一个 Generator 函数中调用另一个 Generator 函数,可以实现更加复杂的控制流程。

ECMAScript 6 的 Generator

在 ES6 中,Generator 函数通过 function* 关键字定义,使用 yield 关键字来中断函数执行并返回当前值。下面是一个简单的示例:

-- -------------------- ---- -------
--------- ------------- -
  ----- --------
  ----- --------
  ------ -------
-

--- --- - --------------
------------------------ -- - ------ -------- ----- ----- -
------------------------ -- - ------ -------- ----- ----- -
------------------------ -- - ------ ------- ----- ---- -

在上面的代码中,Generator 函数 myGenerator 在执行到 yield 关键字时暂停函数的执行,并且返回一个对象,包括当前的值和一个布尔值表示是否执行完毕。使用 next() 方法可以继续执行该 Generator 函数,执行到下一个 yield 关键字时再次中断执行并返回当前值。

ECMAScript 8 的 Generator yield* 表达式

在 ES8 中,新增的 yield* 表达式可以在一个 Generator 函数中调用另一个 Generator 函数,实现更加复杂的控制流程。下面是一个示例:

-- -------------------- ---- -------
--------- ------------ -
  ----- ----
  ----- ----
-

--------- ------------ -
  ----- ----
  ------ -------------
  ----- ----
-

--- --- - -------------
------------------------ -- - ------ ---- ----- ----- -
------------------------ -- - ------ ---- ----- ----- -
------------------------ -- - ------ ---- ----- ----- -
------------------------ -- - ------ ---- ----- ----- -
------------------------ -- - ------ ---------- ----- ---- -

在上面的代码中,我们定义了两个 Generator 函数 generator1generator2。在 generator2 中我们使用 yield* 表达式来调用 generator1,这样 generator2 的执行流程就会转移到 generator1 中,等到 generator1 执行完毕后再返回 generator2 继续执行。可以看到,通过 yield* 表达式,我们可以实现嵌套的 Generator 函数,更加灵活地控制函数执行流程。

JavaScript 引擎的实现

在 JavaScript 引擎中,Generator 的实现是通过生成器对象来实现的。在每次调用 next() 方法时,引擎会根据当前的执行状态,在函数中寻找下一个可以执行的位置并返回执行结果。在进行 yield* 表达式时,引擎会递归执行目标 Generator,直到返回一个 done 属性为 true 的对象,然后回到当前 Generator,继续执行下一个 yield 表达式。

引擎的实现细节和优化会根据不同的浏览器和 JavaScript 引擎而有所不同,但是主要的执行流程和语法规则都是相同的。在我们编写代码的过程中,需要注意一些细节问题,比如避免在 Generator 函数内部使用 return 关键字,因为这会立即结束函数执行并返回结果,而不是暂停函数的执行。

总结

Generator 是 JavaScript 中一个非常强大的语言特性,可以实现异步编程、遍历算法等操作。在 ES8 中,新增的 yield* 表达式更加丰富了 Generator 的使用场景,可以实现更加复杂的控制流程。在实际开发中,我们需要注意一些细节问题,并且充分利用 Generator 的优点,简化代码实现,提高程序的可读性和可维护性。

参考文献

来源:JavaScript中文网 ,转载请注明来源 https://www.javascriptcn.com/post/64d4b1ebb5eee0b525c843c3

纠错
反馈