Iterator 是什么
iterator是遍历数据结构(Array,类Array,Set,Map等)提供的统一接口。
刚接触的小伙伴肯定和我当初一样,对这概念一脸懵逼。我们先看一下它大概长什么样
let itrator = {
next(){
return {value,done} //value是每次返回的值,done是遍历有没有结束
}
}
那这有什么用呢?我们可以在array,set,map等数据结构中实现类似这样的iterator 接口,通过统一的方法的遍历他们,例如:for of。
我们先试着实现一个数组的iterator
Array.prototype.iterator = function(){
let i = 0
return {
next:()=>{
let ret = this.length>i?{value:this[i],done:false}:{value:undefined,done:true}
i++
return ret
}
}
}
let arr = [1,2,3]
let iterator = arr.iterator()
//遍历
let mark = true
while(mark){
let {value,done} = iterator.next()
console.log(value,done);
mark = !done
}
手动遍历的方式也太傻了点吧,赶紧换成es6提供的for of方式来尝尝鲜。源码中返回iterator的方法的属性名是[Symbol.iterator],它是一个Symbol类型。
Array.prototype[Symbol.iterator] = function(){
let i = 0
return {
next:()=>{
let ret = this.length>i?{value:this[i],done:false}:{value:undefined,done:true}
i++
return ret
}
}
}
let arr = [1,2,3]
for(let val of arr){
console.log(val);
}
到这,我们发现只要实现了iterator接口的数据我们都可以用for of遍历了,字符串、map、set等都实现了各自不同的iterator,感兴趣的自己实现下
实现Iterator 接口的数据结构
es6中实现Iterator 接口的数据结构如下
- Array
- Map
- Set
- String
- TypedArray
- 函数的 arguments 对象
- NodeList 对象
既然这样的话,都已经帮我们实现好了,那我们何不干点坏事、拿到它默认的提供的iterator,我们手动遍历它
let arr = [1,2,3]
let iterator = arr[Symbol.iterator]()
let mark = true
while(mark){
let {value,done} = iterator.next()
console.log(value,done);
mark = !done
}
实现一个对象的Iterator
es6中为那多数据结构提供的iterator,为什么就没有对象呢?因为对象的遍历顺序不能确定,需要我们手动指定,es6也给我们提供map这样的有序数据结构。
不给我们提供,那我们自己实现呗
第一种:常规手段
Object.prototype[Symbol.iterator] = function () {
let properties = Reflect.ownKeys(this) //获取普通属性和symbol,map中的symbol属性也可以遍历
let i = 0
return {
next: () => {
let ret = properties.length > i ? { value: [properties[i], this[properties[i]]], done: false } : { value: undefined, done: true }
i++
return ret
}
}
}
let obj = {a:1,b:2}
for(let val of obj){
console.log(val);
}
第二种:借助generator函数
因为generator函数返回的是一个遍历器,需要我们通过next一层层调用,每次调用next返回的value就是yield后执行的结果。
Object.prototype[Symbol.iterator] = function*(){
for(let key in this){
yield [key,this[key]]
}
}
let obj = {a:1,b:2}
for(let val of obj){
console.log(val);
}
言简意赅,恰到好处,这就是代码的魅力
如果对generator函数感兴趣,可以看下我们的另一篇文章juejin.cn/post/684490…