ES6 学习笔记(12) Iterator 和 for...of 循环

1. Iterator(遍历器)概念


Iterator 的作用有三个:一是为各种数据结构,提供一个统一的、简便的访问接口;二是使得数据结构的成员能够按某种次序排列;三是 ES6 创造了一种新的遍历命令for...of循环,Iterator 接口主要供for...of消费。

Iterator 的遍历过程是这样的。

(1)创建一个指针对象,指向当前数据结构的起始位置。也就是说,遍历器对象本质上,就是一个指针对象。

(2)第一次调用指针对象的next方法,可以将指针指向数据结构的第一个成员。

(3)第二次调用指针对象的next方法,指针就指向数据结构的第二个成员。

(4)不断调用指针对象的next方法,直到它指向数据结构的结束位置。

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

2. 默认 Iterator 接口


ES6 规定,默认的 Iterator 接口部署在数据结构的Symbol.iterator属性,或者说,一个数据结构只要具有Symbol.iterator属性,就可以认为是“可遍历的”(iterable)。
原生具备 Iterator 接口的数据结构如下。
Array
Map
Set
String
TypedArray
函数的 arguments 对象
NodeList 对象
一个类部署 Iterator 接口的写法

  class RangeIterator {
    constructor(start, stop) {
      this.value = start;
      this.stop = stop;
    }

    [Symbol.iterator]() { return this; }

    next() {
      var value = this.value;
      if (value < this.stop) {
        this.value++;
        return {done: false, value: value};
      }
      return {done: true, value: undefined};
    }
  }

  function range(start, stop) {
    return new RangeIterator(start, stop);
  }

  for (var value of range(0, 3)) {
    console.log(value); // 0, 1, 2
  }

3. 调用 Iterator 接口的场合


有一些场合会默认调用 Iterator 接口(即Symbol.iterator方法),除了下文会介绍的for...of循环,还有几个别的场合。
(1)解构赋值
(2)扩展运算符
(3)yield*
(4)其他场合
for...of
Array.from()
Map(), Set(), WeakMap(), WeakSet()(比如new Map([['a',1],['b',2]]))
Promise.all()
Promise.race()

4. 字符串的Iterator接口


字符串是一个类似数组的对象,也原生具有 Iterator 接口。

5. Iterator 接口与 Generator 函数


Symbol.iterator方法的最简单实现,还是使用下一章要介绍的 Generator 函数。

6. 遍历器对象的 return(),throw()


遍历器对象除了具有next方法,还可以具有return方法和throw方法。如果你自己写遍历器对象生成函数,那么next方法是必须部署的,return方法和throw方法是否部署是可选的。

7. for...of 循环


一个数据结构只要部署了Symbol.iterator属性,就被视为具有 iterator 接口,就可以用for...of循环遍历它的成员。也就是说,for...of循环内部调用的是数据结构的Symbol.iterator方法。

for...of循环可以使用的范围包括数组、SetMap 结构、某些类似数组的对象(比如arguments对象、DOM NodeList对象)、后文的 Generator 对象,以及字符串。

  • 数组
  • Set和Map结构
  • 计算生成的数据结构
  • 类数组对象
  • 对象

你可能感兴趣的:(ES6 学习笔记(12) Iterator 和 for...of 循环)