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...of、forEach或传统for循环