迭代器
迭代器是ES6标准制定的被设计专用于迭代的对象,带有特定接口。所有的迭代器对象都拥有next()
方法,会返回一个结果对象。该结果对象有两个属性:对应下一个值的value
,以及一个布尔类型的done
,其值为true
时表示没有更多值可供使用。迭代器持有一个指向集合位置的内部指针,每当调用了next()
方法,迭代器就会返回相应的下一个值。
迭代器示例代码如下:
1 | function createIterator(items) { |
生成器
按照ES6标准书写迭代器,有一些复杂,不过好在ES6同时引入了生成器,可以让创建迭代器变得简单。
生成器(generator) 是能返回一个迭代器的函数。生成器函数由放在function
关键字之后的一个星号(*)来表示,并能使用新的yield
关键字。生成器函数是 ES6 的一个重要特性,并且因为它就是函数,所以能被用于所有可用函数的位置。
1 | // 生成器 |
生成器函数最有意思的方面可能就是它们会在每个yield
语句后停止执行。例如,此代码中yield 1
执行后,该函数将不会再执行任何操作,直到迭代器的next()
方法被调用,此时才继续执行yield 2
。
可迭代对象与for-of循环
与迭代器紧密相关的是,可迭代对象(iterable) 是包含Symbol.iterator
属性的对象。这个Symbol.iterator
知名符号定义了为指定对象返回迭代器的函数。在 ES6 中,所有的集合对象(数组、 Set 与 Map )以及字符串都是可迭代对象,因此它们都被指定了默认的迭代器。可迭代对象被设计用于与 ES 新增的 for-of 循环配合使用。
生成器创建的所有迭代器都是可迭代对象,因为生成器默认就会为 Symbol.iterator 属性赋值。
for-of 循环在循环每次执行时会调用可迭代对象的next()
方法,并将结果对象的value
值存储在一个变量上。循环过程会持续到结果对象的done
属性变成true
为止。此处有个范例:
1 | let values = [1, 2, 3]; |
这个 for-of 循环首先调用了values
数组的Symbol.iterator
方法,获取了一个迭代器(对Symbol.iterator
的调用发生在 JS 引擎后台)。接下来iterator.next()
被调用,迭代器结果对象的value
属性被读出并放入了num
变量。num
变量的值开始为 1 ,接下来是 2 ,最后变成 3 。当结果对象的done
变成true
,循环就退出了,因此 num
绝不会被赋值为undefined
。
开发者自定义对象默认情况下不是可迭代对象,但你可以创建一个包含生成器的Symbol.iterator
属性,让它们成为可迭代对象。例如:
1 | let collection = { |
摘录来源
- Nicholas C. Zakas, Understanding ECMAScript 6 中文翻译 http://www.dfhuo.com/es6.pdf