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 函数 generator1
和 generator2
。在 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