Iterator、for…of循环
什么是Iterator接口
- 在整个js过程中,操作某些数据结构,比如Map、Set、数组、对象,它们都可以理解为数据集合,对于数据集合我们怎么去读取,因为数据结构本身不同,我们怎么能用一种相同办法的接口让这些数据结构得到一个统一的读取方式,这就是Iterator接口所要实现的功能
Iterator的基本用法
for…of
- for…of 在数组、Map、Set中使用过
- for…of背后的原理是不断的调用Iterator接口来达到这种形式
- 不同的数据结构,通过for…of统一的形式来达到读取不同数据结构的目标
- 但是for…of背后的Iterator接口是不一样的
{
let arr = ['hello','world'];
let map = arr[Symbol.iterator]();//这个方法一定要返回一个对象,这个对象一定是有next方法的(即map.next())
//数组arr直接调用Symbol.iterator接口,这个接口是数组内部已经帮我们实现了这个接口了,所以直接调用
console.log(map.next());//{value: "hello", done: false}
console.log(map.next());//{value: "world", done: false}
console.log(map.next());//{value: undefined, done: true}
//done说明这个循环是不是还有下一步状态,true说明没有下一步了
//false说明循环还没有结束
//这就是iterator在数组中的应用
//以上Iterator接口是数组内部实现好的
}
//如何手动实现一个Iterator接口
{
//比如定义一个obj,obj内部的数据结构是我们定义的
//如何实现这样的数据结构的Iterator接口
//object本身没有Iterator接口,因为object内部数据是由我们填充的,不知道填充什么样的数据,那就不知道怎么遍历
//数组内部元素就是从下标0、1、2...开始的
//我们自定义一个Interator接口,来实现object的for...of循环
let obj = {
start: [1,2,3],
end: [4,5,6]
//遍历obj,实现先遍历start然后遍历end
//这里的需求不是遍历出key value
[Symbol.iterator](){//声明一个Iterator接口方法//中括号里放置一个变量名,es6新增的方式
let self = this;
let index = 0;//index用于记住当前索引
let arr = self.start.concat(self.end)//合并成一个数组,实现1,2,3,4,5,6的遍历
let len = arr.length;//记住数组长度
//这个方法一定要返回一个对象,这个对象一定是有next方法的
return {
next(){//这里写怎么遍历的过程(重要!!!)
if(index<len){//当前索引小于数组的长度时,返回当前值
return {
//返回值有两部分
//value值(当前遍历的值)
//done表示循环是不是结束了,false表示没结束
value:arr[index++],//默认当前索引累计加1,下一步时就不是重复的
done:false
}
}else{//如果不满足条件,遍历结束
return {
value:arr[index++],
done:true
}
}
}
}
}
}
//验证接口是否部署成功
for(let key of obj){
console.log(key);
//1
//2
//3
//4
//5
//6
}
}
总结
- 不管将来你想遍历什么样的数据结构(数据结构可能复杂可能简单)
- 想自定义部署一个方法,必须按照这样的一个操作
- 最后要返回一个对象,对象一定要包含一个next()方法
[Symbol.iterator](){
//...函数体
return { //返回对象,对象中包含next()方法,next方法返回一个对象,这个对象包含value和done
next(){
return {
value: //...,
done: //false true
}
}
}
}
for…of循环
- for…of背后就是用的Iterator接口
- 如果没有部署Iterator接口,一定要手动部署,才能使用for…of
{
let arr = ['hello','world'];
for(let value of arr){
console.log('value',value);
//hello
//world
}
}