一、概述
1、一种接口,为各种不同的数据结构提供统一的访问机制。任何数据结构只要部署Iterator接口,就可以完成遍历操作
2、调用指针对象的next
方法,就可以遍历事先给定的数据结构
3、每一次调用next
方法,都会返回数据结构的当前成员的信息。具体来说,就是返回一个包含value
和done
两个属性的对象。其中,value
属性是当前成员的值,done
属性是一个布尔值,表示遍历是否结束。
4、凡是部署了Symbol.iterator
属性的数据结构,就称为部署了遍历器接口。调用这个接口,就会返回一个遍历器对象。
二、数据结构的默认Iterator接口
1、对象的Symbol.iterator
属性,指向该对象的默认遍历器方法。
2、具备Iterator接口的原生数据结构:
- 数组
- 某些类似数组的对象
- Set和Map结构。
3、其他数据结构(主要是对象)的Iterator接口,都需要自己在Symbol.iterator
属性上面部署,这样才会被for...of
循环遍历
4、严格地说,对象部署遍历器接口并不是很必要,因为这时对象实际上被当作Map结构使用
5、对一般对象部署迭代器对象:
/** * * @authors Soul (2461358597@qq.com) * @date 2016-06-01 15:34:02 * @version 0.0.1 * @description 给一般对象部署迭代器对象 */ //迭代器对象 const soul_iterator={ soul_index:-1, [Symbol.iterator](){ return this; }, next(){ var arr=this.soul_exchange(); this.soul_index++; return this.soul_index>=arr.length?{value:undefined,done:true}:{value:this[arr[this.soul_index]],done:false}; }, soul_exchange(){ var array=[];//用来存放数字索引和属性名的键值对 var j=0;//用作array数组的索引值 for(let i in this){ if(i!="soul_index"&&i!="next"&&i!="soul_exchange") array[j++]=i; } // console.log(array); return array; } }; //测试对象 function objTest(){} objTest.prototype={ name:"soul", age:21 }; //部署迭代器对象 objTest.prototype.__proto__=soul_iterator; //创建测试对象的实例 var newObj=new objTest(); // for...of 测试 for(let i of newObj){ console.log(i); } //next()方法测试 // console.log(newObj.next()); // console.log(newObj.next()); // console.log(newObj.next()); // console.log(newObj.next());
6、对于类似数组的对象(存在数值键名和length属性),部署Iterator接口,有一个简便方法,就是Symbol.iterator
方法直接引用数组的Iterator接口
NodeList.prototype[Symbol.iterator] = Array.prototype[Symbol.iterator];
7、如果Symbol.iterator
方法对应的不是遍历器生成函数(即会返回一个遍历器对象),解释引擎将会报错
三、调用Iterator接口的场合
1、默认调用Iterator接口的情况:
- 解构赋值
- 扩展运算符 //只要某个数据结构部署了Iterator接口,就可以对它使用扩展运算符,将其转为数组
- yield* //yield*后面跟的是一个可遍历的结构,它会调用该结构的遍历器接口
- for...of
- Array.from()
- Map(), Set(), WeakMap(), WeakSet()(比如
new Map([['a',1],['b',2]])
) - Promise.all()
- Promise.race()
四、字符串的Iterator接口
1、字符串是一个类似数组的对象,也原生具有Iterator接口。
五、Iterator接口和Generator函数
1、Generator可以很容易的实现Iterator接口
2、实现方式:
var myIterable = {}; myIterable[Symbol.iterator] = function* () { yield 1; yield 2; yield 3; };
3、yield命令给出每一步的返回值。
六、Iterator对象的return()和throw()
1、next方法是必须部署的,return
方法和throw
方法是否部署是可选的
2、return方法必须返回一个对象
3、return方法主要用于提前退出
4、throw方法主要是配合Generator函数使用,一般的遍历器对象用不到这个方法
七、for...of
1、凡是部署了Iterator对象的对象,都可以使用for...of取得值