为什么 for of循环可以对数组和字符串进行循环,但是 对象为什么不能使用 for of 循环?

142 阅读2分钟

为什么 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]() 方法一样的效果!