遍历器(Iterator)就是这样一种机制。它是一种接口,为各种不同的数据结构(数组、Set、Map等)提供统一的访问机制。任何数据结构只要部署 Iterator 接口,就可以完成遍历操作(即依次处理该数据结构的所有成员)供 for…of消费。
for…of遍历机制:
- 会寻找被遍历对象是否含有Symbol.iterator方法,如果没有报错
 - 当for…of遍历的时候,会调用遍历器对象的next方法
 - 当done为false的时候继续遍历,为true的时候,停止遍历
 
想要被for…of 遍历:
- 部署Symbol.iterator方法,返回迭代器对象iterator object
 - 迭代器对象中提供next方法被for…of遍历
 - next方法返回 {value: any,done:Boolean}
 
原生具备 Iterator 接口的数据结构如下。
- Array
 - Map
 - Set
 - String
 - TypedArray
 - 函数的 arguments 对象
 - NodeList 对象
 
对象(Object)之所以没有默认部署 Iterator 接口,是因为对象的哪个属性先遍历,哪个属性后遍历是不确定的,需要开发者手动指定。本质上,遍历器是一种线性处理,对于任何非线性的数据结构,部署遍历器接口,就等于部署一种线性转换
部署了遍历器的数据结构我们称为是可迭代的(iterable),也就是可以:
- for..of
 - rest、spread 扩展运算符
 - yield*
 - Array.from()
 
举例:
Object对象正常是不可迭代的
要想range可迭代,我们按照以上步骤来实现下:
let range = {from: 1,to: 5,};// 1. for..of 调用首先会调用这个:range[Symbol.iterator] = function () {// ……它返回迭代器对象(iterator object):// 2. 接下来,for..of 仅与此迭代器一起工作,要求它提供下一个值return {current: this.from,last: this.to,// 3. next() 在 for..of 的每一轮循环迭代中被调用next() {// 4. 它将会返回 {done:.., value :...} 格式的对象if (this.current <= this.last) {return { value: this.current++, done: false };} else {return { value: undefined, done: true };}},};};for (let r of range) {console.log(r);}
字符串原生就部署了遍历器
const str = 'helllo';const iterator = str[Symbol.iterator]();iterator.next(); //{value: 'h', done: false}iterator.next(); //{value: 'h', done: false}iterator.next(); //{value: 'h', done: false}...
iterator与generator
let range = {from: 1,to: 5,*[Symbol.iterator]() { // [Symbol.iterator]: function*() 的简写形式for(let value = this.from; value <= this.to; value++) {yield value;}}};
