引言
在 ES6 中,我们引入了 generator 函数,它通过 yield 关键字使得函数执行可以暂停,并且随时可以恢复。ES9 中对 generator 函数做了一些改进,其中最重要的改进之一是实现了多个迭代器之间相互进行“通信”,这一改进非常有用,可以开发出更复杂和有趣的应用程序。
迭代器和生成器
在深入探讨 generator 函数的改进之前,我们需要先了解迭代器和生成器的基本概念。
在 JavaScript 中,迭代器主要有两个方法:next()
和 return()
。其中,next()
方法用于取出下一个元素,return()
方法用于结束迭代器的操作。
而生成器则是一种特殊的函数,其可以通过 yield 关键字使函数执行可以暂停,并且随时可以恢复。
ES9 中 generator 函数的改进
在 ES9 中,generator 函数的最重要的改进之一是实现了多个迭代器之间相互进行“通信”。
在 ES6 中,我们可以通过 yield 表达式将值从生成器迭代器传递到生成器函数。而在 ES9 中,我们可以通过 yield*
表达式将一个迭代器中的值传递给其他迭代器。
下面是一个简单的例子,我们可以借此了解这种改进的作用和实现方式:
-------- ------ - ----- -- ----- -- ----- -- - -------- ------ - ----- -- ------ ------ ----- -- - --- ---- - -- ------ - --------------- -
在这个例子中,我们定义了两个生成器函数,分别是 foo()
和 bar()
。其中,foo()
函数返回一个简单的迭代器,它产生三个数字:1、2 和 3。而 bar()
函数则使用 yield* 将 foo() 函数返回的迭代器中的值传递给外层的迭代器。
在最后的 for 循环中,我们迭代了 bar() 函数返回的迭代器,输出了下面这些数字:
- - - - -
从上面的例子中可以看出:在 ES9 中,使用 yield* 实现多个迭代器之间的通信变得非常简单和方便。
深度分析
上面的例子过于简单,下面我们来看一个更复杂的例子,从中更深入地了解 yield* 的用法。
我们假设有一个学生名册,其中包含了学生的姓名、班级、考试科目和考试成绩。其中,每个学生可能在多个科目中都参加了考试。我们需要编写程序对学生进行分类统计,最终输出每个班级中每个学生每个科目的总分数、平均分数、最高分数和最低分数。
为了实现这个功能,我们需要实现三个函数:
group(students)
:将所有学生按班级进行分组。score(students)
:将所有同班的同学按科目进行分组,并计算总分数、平均分数、最高分数和最低分数。main(students)
:主函数,将上述两个函数组合起来,输出结果。
我们可以通过 ES9 中的 generator 函数实现这个功能:
-------- ---------------- - ----- ------ - --- ------ --- ---- ------- -- --------- - --- ----- - -------------------------- -- ------- -- ------ --------------------- --- ------------ - ----- - - ---------------- -- --------- --- ----- - ------------------------- ------- - -------------------------------- --------- - ------ --------------------- - -------- ---------------- - ----- ------ - --- ------ --- ---- ------- -- --------- - --- ----- - -------------------------- -- ------- -- ------ --------------------- --- ------------ - ----- - - ---------------- -- --------- --- ----- - ------------------------- ------- - --- ------- - ----------------------------------------- -- --------- -- ------ ------------------ --- ------------ - ------- - - ----------- -- ------ -- --------- ---------- --------- -------- -- ---------------------------------------- - -------- - ------------------ -- -------------- ---------------- ---------------- - -------------------------- --------------- ---------------- - -------------------------- --------------- --------------------- -- -------------- - ------ ------------------------------ -- -- ------ ------------ --------- ---------------------------------------- -- -- ----- ------------- -------- --------------- --- ---- - -------- -------------- - --- ---- ---------- -- ---------------- - ----------------------------------------------- -------------------------------------- --------------------------------------------------- --- ---- ------- -- --------------------------- - ------------------------------------------- ---------------------------------- ---------------------------------------------------------------------------------------------------------------------------------------------- - -------------------------- - - -
在上面的代码中,我们定义了三个 generator 函数分别为:group、score 和 main。在 group 函数中,我们首先按照班级进行分组,然后调用 yield* 将所有分组的结果迭代出来。在 score 函数中,我们按照班级和科目进行分组,并计算总分数、平均分数、最高分数和最低分数,然后调用 yield* 将结果迭代出来。最后,在 main 函数中,我们将上述两个函数组合起来,输出结果。
结论
在 ES9 中,实现多个迭代器之间相互进行“通信”变得非常简单和方便,我们只需要使用 yield* 表达式即可。借助这个特性,我们可以编写更复杂和有趣的应用程序,提高我们的编程效率和代码可读性。
在使用 yield* 表达式时,我们需要注意以下几点:
- 如果迭代器 A 中的一个元素被 yield* 到另一个迭代器 B 中,那么当执行迭代器 B 的 return() 方法时,迭代器 A 的 return() 方法也会被自动调用。
- 当使用 yield* 表达式时,最终的返回值是被 yield 的迭代器自己的 return() 方法的返回值。
- 当我们使用 yield* 表达式时,我们可以通过在另一个迭代器中使用 yield 表达式来直接得到被 yield 的值。
在编写使用 yield* 表达式的代码时,我们需要更加细心,避免出现意外的错误。我们还需要注意所使用的 JavaScript 环境是否支持 ES9 中的 generator 函数特性。
来源:JavaScript中文网 ,转载请注明来源 本文地址:https://www.javascriptcn.com/post/67397ee3dee7df6752420aa0