遍历器(Iterator)是一种接口,为各种不同的数据结构提供统一的访问机制。任何数据只要部署Iterator接口,就可以完成遍历操作。

作用有三:

  • 为各种数据提供统一的访问接口。
  • 使得数据结构的成员能够按某种次序排列。
  • ES6创造了新的遍历命令for...of 循环,提供遍历器使用。

换句话说,如果使用了for...of循环遍历某种数据结构时,该循环就会去寻找 Iterator 接口。只要某个数据结构部署了 Iterator接口,就称这种数据结构为“可遍历的(iterable)”

而默认的Iterator接口,部署在数据结构的Symbol.iterator属性,一个数据只要有这个属性,就可以认为是“可遍历的”。Symbol.iterater属性其实是个函数,执行这个函数,就会返回一个遍历器。而属性名Symbol.iterater 看得出来,是Symbol对象的iterator属性,类型为Symbol的特殊值,所以放在放括号里!(忘记可回看Symbol知识)

Symbol.iterater返回的函数,这个函数的执行过程是这样的:

  • 创建一个指针对象,指向当前的起始位置。
  • 第一次调用指针对象的next方法,指向数据结构的第一个成员。
  • 第二次同样的操作,只不过是指向数据结构第二个成员。
  • 不断的调用next方法,直到指向结束位置。

同时,每一次调用next方法,都会返回数据结构的当前成员的信息,其中返回的是valuedone两个属性的对象。value属性是当前成员的值,done属性是一个布尔值,表示遍历是否结束。

以上根据上面的执行过程来模拟遍历器代码:

  1. function makeIterator(array){
  2. let nextIndex = 0;
  3. return {
  4. next: function(){
  5. return nextIndex < array.length ?
  6. {value: array[nextIndex++], done: false} :
  7. {value: undefined, done: true};
  8. }
  9. }
  10. }
  11. let it = makeIterator(['a', 'b'])
  12. it.next() //{ value: "a", done: false }
  13. it.next() //{ value: "b", done: false }
  14. it.next() //{ value: undefined, done: true}

由于Iterator只是把接口规格加到数据结构上,所以,遍历器和要遍历的那个数据结构,实际上是分开的。

当然,ES6有些数据原生具备了Iterator接口,如下:

  • Array
  • Map
  • Set
  • String
  • TypedArray
  • 函数的arguments对象
  • NodeList对象

例如:

  1. let arr = [1,2,3]
  2. let iter = arr[Symbol.iterator]()
  3. iter.next() //{ value: 1, done: false }
  4. iter.next() //{ value: 2, done: false }
  5. iter.next() //{ value: 3, done: false }
  6. iter.next() //{ value: undefined, done: true }

因为原生就自带,所以可以直接获取到Iterator的方法!

而Object却没有这样的遍历器,因为Object需要哪个先执行,哪个个后执行,是不确定的,需要开发者自己动手去设置。不过也没什么必要,要真部署的话就和Map没什么区别的了。

部署过程分两种,第一种使用class部署,第二种使用了原型链上部署。具体部署过程就不细说了!

调用Iterator接口的场合

有些场合会默认调用 Iterator接口(即Symbol.iterator方法),除了for...of会调用外,还有:

  • 解构赋值:对数组和Set结构进行解构赋值时,会默认调用Symbol.iterator方法。
  • 扩展运算符:实际上,只要任何部署了Symbol.iterator,都可以使用扩展运算符。
  • yield*yield*后面跟的是一个可遍历的结构,他会调用该结构的遍历器接口。

同时,因为数组的遍历会调用遍历接口,所以任何接受数组作为参数的场合,其实都调用了遍历器接口。如下例子:

  • for...of
  • Array.from
  • Map()Set()WeakMap()WeakSet() 如(new Map([['a', 1], ['b', 2]])
  • Promise.all()
  • Promise.race()

以上是关于数组的遍历器。