迭代器

Iterator 实现原理

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

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

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

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

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

ES6 里的迭代器并不是一种新的语法或者是新的内置对象(构造函数), 而是一种协议,所有遵循了这个协议的对象都可以称之为迭代器对象,所以说迭代器是一种协议,一个统一的接口标准,两个属性都不返回值也不会报错,但是不符合协议标准了,就不能称作迭代器了

如何部署 Iterator 接口

在 ES6 中,有三类数据结构原生具备 Iterator 接口:数组、某些类似数组的对象、Set 和 Map 结构,对象(Object)之所以没有默认部署 Iterator 接口,是因为对象的哪个属性先遍历,哪个属性后遍历是不确定的,需要开发者手动指定。

const arr = ['a', 'b', 'c'];
const iterator = arr[Symbol.iterator]();
const a = iterator.next();
console.log(a)   //{value: 'a', done: false}
// 遍历一个迭代器
const itor = this.m_measureObjectMap.values();
let result: IteratorResult<MeasureObject>;
while (result = itor.next(), !result.done) {
  const value = result.value;
}

for-of 与 for-in

for…in 遍历每一个索引值,而 for…of 遍历每一个属性值。

在对象没有部署 Iterator 接口的情况下调用 for…of 会报错。

当一个部署了 Iterator 接口的对象调用for…of时,实现的步骤是这样的:

  1. 调用对象的 Symbol.Iterator 的属性获得遍历器生成函数;
  2. 调用遍历器生成函数返回遍历器对象, 其实 for…of 就相当于一直调用遍历器对象的 next 方法,直到返回 done 为 true;
const arr = [4,5,6]
for(const v in arr) {
  console.log(v) // 0 1 2 取出便利对象的索引值
}

for(const v of arr) {
  console.log(v) // 4 5 6 取出遍历对象的元素值
}