简介
- 是一种接口机制,为各种不同的数据结构提供统一访问的机制
- 主要供for … of 消费
- 让不支持遍历的数据结构”可遍历”,最强大之处
手写遍历器
function makeIterator(arr) {
let nextIndex = 0
return {
next() {
return nextIndex < arr.length ? {
value: arr[nextIndex++],
done: false
} : {
value: undefined,
done: true
}
}
}
}
let it = makeIterator(['a', 'b', 'c'])
console.log('it:', it.next())
console.log('it:', it.next())
console.log('it:', it.next())
console.log('it:', it.next())
支持Iterator接口的数据
用map数据进行举例
let map = new Map()
map.set('name', 'es')
map.set('age', 5)
map.set('school', 'imooc')
let it = map[Symbol.iterator]()
console.log('it:', it.next())
console.log('it:', it.next())
console.log('it:', it.next())
console.log('it:', it.next())
手写底层迭代器
const course = {
allCourse: {
pc: ['es', '小程序', 'vue', 'react'],
backend: ['java', 'python', 'springboot'],
app: ['Android', 'ios']
}
}
for (let data of course) {
console.log('data', data)
}
自行实现next() 方法
可迭代协议:Symbol.iterator
迭代器协议::return {next(){return {value, done}}}
const course = {
allCourse: {
pc: ['es', '小程序', 'vue', 'react'],
backend: ['java', 'python', 'springboot'],
app: ['Android', 'ios']
}
}
course[Symbol.iterator] = function () {
let allCourse = this.allCourse
let keys = Reflect.ownKeys(allCourse)
console.log('keys:', keys)
let values = []
return {
next(){
// 因为初始化的时候,values是空数组,长度为0,需要取反
if (!values.length) {
if (keys.length) {
values = allCourse[keys[0]]
keys.shift()
}
}
return {
// 这里有个细节,先判断长度然后执行shift() ,避免对长度判断出错
done: !values.length,
value: values.shift()
}
}
}
};
for (let data of course) {
console.log('遍历', data)
}
这种处理办法虽然看起来很繁琐,但是很适合处理大型项目中复杂数据结构无法遍历,我们可以通过这种方式来重构 for of 循环的底层遍历原理,实现数据的遍历
与generator相结合
const course = {
allCourse: {
pc: ['es', '小程序', 'vue', 'react'],
backend: ['java', 'python', 'springboot'],
app: ['Android', 'ios']
}
}
course[Symbol.iterator] = function* () {
let allCourse = this.allCourse
let keys = Reflect.ownKeys(allCourse)
let values = []
while (1) {
if (!values.length) {
if (keys.length) {
values = allCourse[keys[0]]
keys.shift()
yield values.shift()
} else {
return false
}
} else {
yield values.shift()
}
}
};
for (let data of course) {
console.log('generator遍历', data)
}