这是一篇简短但有用的文章,对于将来使用JavaScript迭代器的开发人员来说。

在我们了解js中的迭代器之前,请记住什么是Symbol :
Symbol是唯一且不变的标识符。 使用Symbol() 函数创建的 ,也可以标记为Symbol('foo')。 具有相同标签的符号彼此不相等,通常,任何符号都不彼此相同(请记住唯一性)。
有系统符号,例如Symbol.iterator , Symbol.toPrimitive等。 系统字符由语言本身使用,但是我们也可以使用它们来更改某些对象的默认行为。
符号是es6规范的一部分,因此根本就不支持它们( caniuse )。
关于Symbol.iterator
基本上,在迭代对象的属性时,语言会在for ... of循环中使用此符号。 它也可以直接用于内置数据类型:
const rangeIterator = '0123456789'[Symbol.iterator](); console.log(rangeIterator.next());
此示例适用于字符串,因为String.prototype具有自己的迭代器( spec )。 js中可迭代类型的列表: 字符串,数组,TypedArray,映射,集合。
除了循环外,javascript在以下构造中使用Symbol.iterator : 传播算子,yield , destructuring分配 。
调用[Symbol.iterator]()返回一个迭代器接口,如下所示:
Iterator { next();
.next()、. return()、. throw()方法准备(然后我们将了解如何)方法并返回以下形式的对象:
{ value - , done - }
例如,当迭代过早结束时,将使用.return()和.throw()方法。 您可以在ecmascript规范中阅读有关它们的更多信息。
在其结构中使用Symbol.iterator
作为示例,让我们创建自己的结构,可以使用...的...对其进行迭代,还可以将Symbol.iterator与上述语言结构一起使用。
想象一下,我们有一条穿越多个站点的路线,并且我们想沿着该路线对每个站点进行操作,例如,将其显示在控制台中。
创建一个路由类:
class Route { stations;
如您所见,我们的Route实现了Symbol.iterator方法,因此Route是一个可迭代的实体( spec ),这意味着我们可以使用for ... of (在研究RouteIterator的实现之后 )进行遍历 。
[Symbol.iterator]()方法将被调用与调用它一样多的次数。 也就是说,如果几个周期试图一个接一个地遍历该路线 ,则将为每个周期调用[Symbol.iterator]() ,因此对于每个调用,我们都会创建一个RouteIterator的新实例。
现在让我们了解RouteIterator本身。 此类为Route实体实现迭代器接口。 让我们看一下:
class RouteIterator { _route;
在此类中,我们可以访问可迭代的集合( route属性),并且nextIdx是指向集合中下一个值的指针。
next()方法首先检查路由是否已完成,如果已完成,则返回迭代已完成。 否则,我们将取路由集合中的下一个值,即迭代未完成,移动指针并返回结果。
现在,我们可以通过...的路线收集:
const route = new Route(['', '', '']) for (let item of route) { console.log(item); }
此代码将列出我们传递给Route的站点。
现在,我们将使用函数生成器浏览各个工作站:
function* gen() { yield* route; return 'x';
Symbol.iterator用于重组 :
const [a, b, c] = route;
和传播算子:
function test(a, b, c) { console.log(a, b, c) } test(…route)
结果
我们创建了我们的类,使其变得可迭代并与javascript构造一起使用。 谢谢您的关注=)。
用料
仅一篇文章就不可能完全掌握新材料,因此这里有一些其他内容:
关于Guru重构书中的迭代器模式
关于Ilya Kantor和MDN上的Symbol