在 JavaScript 中,集合是一种重要的数据类型。ES7 提出了 Iterable、Iterator、Generator 三个新概念,使得集合变得更加容易操作和管理。在本文中,我们将详细探讨它们的定义、用法以及各自之间的关系。
Iterable
Iterable 原意是“可迭代的”,它是一种可以被迭代的对象,也就是说可以通过 for...of 循环进行遍历。具体来说,Iterable 对象必须实现一个名为 @@iterator 的方法,并且返回一个 Iterator 对象。例如:
-- -------------------- ---- ------- ----- --- - - ------------------- - --- - - -- ------ - ------ - ------ - ------ ---- ----- - - - -- - -- - -- --- ------ ---- -- ---- - ------------------ -
上述代码中,我们定义了一个 obj 对象,同时实现了 @@iterator 方法并返回了一个包含 next 方法的对象。for...of 循环通过 obj 对象的 @@iterator 方法得到了 Iterator 对象,有了 Iterator 对象,后续的遍历就可以依靠 next 方法来完成。
需要注意的是,如果一个对象不是 Iterable,那么它就无法使用 for...of 循环来遍历。
Iterator
Iterator 原意是“迭代器”,它是一个带有 next 方法的对象,next 方法用来返回当前迭代位置的数据。具体来说,next 方法返回一个包含 value 和 done 两个属性的对象,value 属性表示当前迭代位置的数据,done 属性表示是否迭代完成。
Iterator 对象由 Iterable 对象生成,例如前文中的 obj 对象。Iterator 对象可以通过调用自己的 next 方法来进行遍历。一旦迭代完成,next 方法就会返回 { done: true },因此可以利用这个特性来写一个通用的迭代器函数实现:
-- -------------------- ---- ------- -------- --------------------- - --- - - -- ------ - ------ - ------ - - ------------ - - ------ ----------- ----- ----- - - - ----- ---- -- - -- - ----- ---- - ------------------ -- -- -- ---- --- ------ - ------------ ----- -------------- - -------------------------- ------ - ------------ -
Generator
Generator 原意是“生成器”,它是 ES6 中新增的一种函数类型。Generator 函数是一个状态机,内部可以定义多个 yield 表达式,yield 表达式定义了内部状态的输出值。例如:
-- -------------------- ---- ------- --------- ----- - ---------------- ---- ----- -- ---------------- ---- ----- -- ---------------- ---- - ----- ---- - ------ ------------------------------- ------------------------------- -------------------------------
上述代码中,我们定义了一个 Generator 函数 foo,它内部定义了三个 yield 表达式。每次调用 next 方法,Generator 函数就会运行到下一个 yield 表达式并暂停,返回一个包含 value 和 done 两个属性的对象。调用 next 方法时,可以向 Generator 函数传递一个值,这个值会成为 yield 的返回值。例如:
-- -------------------- ---- ------- --------- ----- - ---------------- ---- ----- - - ----- -- ---------------- --- --- ----- - - ----- -- ---------------- --- --- - ----- ---- - ------ ------------------------------- ------------------------------------ ------------------------------------
上述代码中,第一个 next 方法不需要传递参数,因为第一个 yield 表达式不会接收到任何值。第二个 next 方法传递了一个 "bar" 参数,这个参数会赋值给 const a。第三个 next 方法传递了一个 "baz" 参数,这个参数会赋值给 const b。
需要注意的是,当 Generator 函数的代码运行完毕之后,再次调用 next 方法将会执行完毕但不会返回任何数据。因此可以利用这个特性来定义一个无限循环的 Generator 函数:
-- -------------------- ---- ------- --------- ----- - --- - - -- ----- ------ - ----- ---- - - ----- ---- - ------ ------------------------------- ------------------------------- -------------------------------
上述代码中,我们定义了一个无限循环的 Generator 函数 foo,每次返回自增的 i 属性。
总结
Iterable、Iterator、Generator 分别是可迭代的对象、迭代器对象、生成器函数。它们可以使得集合的操作更加容易和灵活。需要注意的是,Generator 函数需要运行才能返回数据,因此需要配合 Iterable 和 Iterator 对象来使用。在实际开发中,我们可以充分利用这些对象的特性,来简化和优化代码。
来源:JavaScript中文网 ,转载请注明来源 https://www.javascriptcn.com/post/6480831848841e9894ff4199