为什么 for of 循环对象会报错?我们测试一下:
let arr = [1,2,3,4,5]
let str = '1,2,3'
let obj = {a:1,b:2}
for (let i of arr) {
console.log(i) // 1,2,3,4,5
}
for (let i of str){
console.log(i)// 1,2,3
}
for (let i of obj) {
console.log(i) // 报错: obj is not iterable
}
结果如下:
let arr = [1,2,3,4,5]
let str = '1,2,3'
let obj = {a:1,b:2}
console.log(arr) // 因为 arr数组原型里面有这个属性:Symbol(Symbol.iterator):ƒ values()
console.log(Object.getPrototypeOf(str)) // 使用 Object.getPrototypeOf()方法 获取到 str 字符串的原型可以看到也是有这个属性的:Symbol(Symbol.iterator):ƒ [Symbol.iterator]()
console.log(obj) // 但是 对象没有这个属性,所以没有迭代器,所以无法使用 for of 进行循环
那么问题来了 Symbol(Symbol.iterator)这个属性是什么呢?
结果如下:
let arr = [1,2,3,4,5]
// 我们看一下这个属性方法是什么值
console.log(arr[Symbol.iterator]()) // Array Iterator {}
可以看到有个 next()方法
next:ƒ next()
调用这个属性下面有个 next 方法,我们进行调用看一下返回什么值
//把arr[Symbol.iterator]()赋值给一个变量,使用这个变量直接调用 next 方法显示如下:
var iter = arr[Symbol.iterator]()
console.log(iter.next())// {value: 1, done: false} , value 结果 为 1, 但是迭代还没结束,我们继续
console.log(iter.next())// {value: 2, done: false}
console.log(iter.next())// {value: 3, done: false}
console.log(iter.next())// {value: 4, done: false}
console.log(iter.next())// {value: 5, done: false}
console.log(iter.next())// {value: undefined, done: true} , 当迭代到 第五次时,数组已经循环完 所以返回 undefined ,done显示为 true 迭代完成
那么,结果已经出来了,我们可以自己写一个 iterator 函数,实现调用 next方法进行返回对应的值:
// 结果如下:
let arr = [1,2,3,4,5]
function myIterator(arr){
let index = 0; // 首先定义一个集合 为index 默认为 0
return { // 然后 抛出一个 next 方法
next(){
if(index < arr.length){ // 判断只要 index 所以不超过 arr 数组length长度的时候才会返回这个 对象
return{
value:arr[index++],done:false //因为每一次迭代之后都需要 value自加 所以需要 index索引 ++
}
}else{
return{
value:undefined,done:true // 当 index 索引超出 arr 数组length长度的时候那么就返回这个对象,value 为undefined,done为true
}
}
}
}
}
//结果如下:
let inter = myIterator(arr);
console.log(inter.next()) // {value: 1, done: false}
console.log(inter.next()) // {value: 2, done: false}
console.log(inter.next()) // {value: 3, done: false}
console.log(inter.next()) // {value: 4, done: false}
console.log(inter.next()) // {value: 5, done: false}
console.log(inter.next()) // {value: undefined, done: true}
跟最上面原生数组 arr[Symbol.iterator]() 方法一样的效果!