for in 可以迭代对象和数组吗?

4 阅读2分钟

for...in 可以迭代对象和数组,但不建议用来遍历数组,因为它有一些需要注意的特性。

1. 遍历对象 ✅

for...in 主要用于遍历对象的可枚举属性(包括原型链上的属性):

javascript

const obj = {
    name: 'Alice',
    age: 25,
    city: 'Beijing'
}

for (let key in obj) {
    console.log(key, obj[key])
}
// 输出:
// name Alice
// age 25
// city Beijing

2. 遍历数组 ⚠️

for...in 虽然可以遍历数组,但存在几个问题:

问题一:遍历的是索引(字符串类型)

javascript

const arr = ['a', 'b', 'c']

for (let index in arr) {
    console.log(typeof index, index, arr[index])
}
// 输出:
// string 0 a
// string 1 b
// string 2 c

问题二:会遍历数组对象上的自定义属性

javascript

const arr = ['a', 'b', 'c']
arr.customProp = 'hello'

for (let index in arr) {
    console.log(index, arr[index])
}
// 输出:
// 0 a
// 1 b
// 2 c
// customProp hello  ← 意外的属性也会被遍历

问题三:会遍历原型链上的可枚举属性

javascript

Array.prototype.someMethod = function() {}

const arr = ['a', 'b', 'c']

for (let index in arr) {
    console.log(index)
}
// 输出:
// 0
// 1
// 2
// someMethod  ← 原型链上的属性也被遍历了

3. 更好的遍历方式

遍历数组推荐使用:

javascript

const arr = ['a', 'b', 'c']

// for...of(ES6,遍历值)
for (let value of arr) {
    console.log(value)
}

// forEach
arr.forEach((value, index) => {
    console.log(index, value)
})

// 传统 for 循环
for (let i = 0; i < arr.length; i++) {
    console.log(i, arr[i])
}

遍历对象推荐使用:

javascript

const obj = { name: 'Alice', age: 25 }

// Object.keys() - 遍历自身可枚举属性
Object.keys(obj).forEach(key => {
    console.log(key, obj[key])
})

// Object.entries() - 同时获取键和值
Object.entries(obj).forEach(([key, value]) => {
    console.log(key, value)
})

// Object.values() - 只遍历值
Object.values(obj).forEach(value => {
    console.log(value)
})

对比

遍历方式对象数组说明
for...in✅ 适用⚠️ 不推荐遍历可枚举属性,会包括原型链
for...of❌ 不适用✅ 推荐遍历可迭代对象的值
Object.keys()✅ 推荐❌ 不适用只遍历自身可枚举属性
forEach❌ 不适用✅ 推荐数组专用方法

建议

  • 遍历对象使用 Object.keys()Object.entries() 或 for...in(配合 hasOwnProperty 检查)
  • 遍历数组使用 for...offorEach 或传统 for 循环