ES6 和 ES8 中的迭代器 —— 如何使用 Iterator 和 Generator 函数

阅读时长 6 分钟读完

在 JavaScript 的 ES6 和 ES8 中,迭代器(Iterator)和生成器(Generator)函数被引入进来。迭代器是一个实现了特定迭代协议的对象,用于遍历对象的元素。生成器函数则可以用于简化迭代器的使用,让开发者更容易地实现迭代器协议。

迭代器的基本用法

在 ES6 中,迭代器协议规定了对象必须实现一个 next() 方法,这个方法返回一个对象,包含两个属性:valuedone。其中,value 表示下一个元素的值,done 表示迭代器是否已经结束。

下面是一个迭代数组元素的示例:

在这个示例中,我们使用了数组的 Symbol.iterator 属性获取了一个迭代器对象 it。在每次调用 next() 方法时,我们可以得到下一个元素的值和一个 done 标记,来判断是否已经迭代完毕。

生成器函数的基本用法

虽然迭代器协议能够让我们手动遍历元素,但是在实际开发中,我们往往需要处理更复杂的场景,比如异步数据操作。这时,生成器函数可以帮助我们更好地抽象这些复杂的操作。

生成器函数使用 function* 来声明,函数内部可以使用 yield 关键字来暂停函数的执行,并返回一个值。每次调用生成器函数时,都会返回一个迭代器对象。下面是一个简单的生成器函数的示例:

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

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

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

在这个示例中,我们定义了一个生成器函数 myGenerator(),它会依次返回 1、2、3 三个值。在每次调用 next() 方法时,函数会执行到 yield 关键字,暂停执行并返回当前值。当函数执行完毕时,迭代器对象的 done 属性会变为 true

生成器函数的进阶用法

生成器函数不仅可以帮助我们更好地抽象复杂操作,还可以与其他 JavaScript 特性混用,提供更强大的功能。

生成器函数 + Promise

在 ES8 中,我们可以使用 asyncawait 来处理异步任务,但是在某些情况下,使用生成器函数可能更加灵活。例如,我们希望按顺序执行多个异步任务:

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

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

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

在这个示例中,我们定义了一个生成器函数 getDataSequence(),它依次调用三个异步任务。在主程序中,我们通过调用迭代器的 next() 方法,依次执行异步任务,并使用 Promise 的链式调用来处理每一个返回结果。

生成器函数 + 双向通信

生成器函数除了可以从外部接收数据,还可以向外部发送数据。使用 yield 关键字时,可以把数据发送给外部,使用 next() 方法时,可以从外部获取数据。下面是一个双向通信的示例:

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

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

在这个示例中,我们定义了一个生成器函数 twoWayGenerator(),它会持续返回一个对象,包含当前的 xy 值。在主程序中,我们首先调用一次 next() 方法,从生成器函数中获取当前的 xy 值。之后,我们通过再次调用 next() 方法,把数据发送给生成器函数,生成器函数会处理后返回一个新的对象。

总结

ES6 和 ES8 中的迭代器和生成器函数是一个非常强大的特性,它们可以帮助我们更好地处理各种复杂场景。在使用时,需要注意迭代器协议的规定,以及生成器函数的特点。在实际开发中,我们可以将它们与 Promise、双向通信等特性混用,提高代码的简洁度和可维护性。

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

纠错
反馈