for...in
(1) 遍历 对象上的、对象继承的、对象原型上的 可枚举属性 的属性名(key)
(2) 输出的顺序不是固定的,因此不适合遍历数组
(3) 如果迭代的对象的变量值是 `null` 或者 `undefined`, for... in不执行循环体,建议在使用for... in循环之前,先检查该对象的值是不是null或者undefined
for...of
(1) 遍历可迭代对象的属性值(value)
(2) 只会遍历可迭代对象(array,string,类数组如 nodeList 和 arguments,map,set,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 生成的迭代器对象,可以参考这篇文章