转自:https://www.cnblogs.com/realsoul/p/5550508.html
一、概述
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取得值