【JS】for...in 和 for...of 的区别

68 阅读1分钟

for...in

(1) 遍历 对象上的、对象继承的、对象原型上的 可枚举属性 的属性名(key)
(2) 输出的顺序不是固定的,因此不适合遍历数组
(3) 如果迭代的对象的变量值是 `null` 或者 `undefined`, for... in不执行循环体,建议在使用for... in循环之前,先检查该对象的值是不是null或者undefined

for...of

(1) 遍历可迭代对象的属性值(value)
(2) 只会遍历可迭代对象(arraystring,类数组如 nodeList 和 arguments,mapset,generator 生成的迭代器对象等),这些对象里面有个 [Symbol.iterator] 方法,是一个迭代器,其中可以自定义要迭代的数据

总的来说,for...in 适合遍历对象,for...of 适合遍历数组

想要用 for...of 遍历普通对象,该怎么办?

可以为对象添加一个 [Symbol.iterator] 方法,模拟迭代器
let classes = {
    stus: ["小明", "小红", "小刚", "小黄"],
    [Symbol.iterator]: function(){
        let index = 0
        const _this = this
        const length = this.stus.length
        return {
            next(){
                if(index < length){
                    return { value: _this.stus[index++], done: false }
                } else {
                    return { value: undefined, done: true}
                }
            }
        }
    }
}

const iter = classes[Symbol.iterator]()


// 可以一个一个输出
console.log(iter.next())  // {value: '小明', done: false}
console.log(iter.next())  // {value: '小红', done: false}
console.log(iter.next())  // {value: '小刚', done: false}
console.log(iter.next())  // {value: '小黄', done: false}
console.log(iter.next())  // {value: undefined, done: true}

// 也可以使用 for...of 一次性遍历
// for(const val of classes){
//     console.log(val)
// }

关于上面提到的 generator 生成的迭代器对象可以参考这篇文章