为何使用 'for...in' 迭代数组不是个好主意?

为何使用 ‘for…in’ 迭代数组不是个好主意?

技术背景

在 JavaScript 中,有多种方式可以对数组进行迭代,其中 for...in 是一种常用的循环结构。然而,使用 for...in 来迭代数组往往不是一个好的选择,这与 JavaScript 数组的特性以及 for...in 循环的工作原理有关。

实现步骤

正常数组迭代

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
var a = [];
a[5] = 5;

// 使用普通 for 循环迭代
for (var i = 0; i < a.length; i++) {
console.log(a[i]);
}
// 输出:
// undefined
// undefined
// undefined
// undefined
// undefined
// 5

// 使用 for...in 循环迭代
for (var x in a) {
console.log(x);
}
// 输出:
// 5

原型链影响

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// 修改数组原型
Array.prototype.foo = 1;

var a = [1, 2, 3, 4, 5];
for (var x in a) {
console.log(x);
}
// 输出:
// 0
// 1
// 2
// 3
// 4
// foo

核心代码

1
2
3
4
5
6
7
8
9
10
11
12
13
// 避免 for...in 循环带来的问题,使用普通 for 循环
var arr = [1, 2, 3];
for (var i = 0; i < arr.length; i++) {
console.log(arr[i]);
}

// 如果要使用 for...in 循环并过滤继承属性
var obj = {a: 1, b: 2};
for (var prop in obj) {
if (Object.prototype.hasOwnProperty.call(obj, prop)) {
console.log(prop, obj[prop]);
}
}

最佳实践

  • 使用普通 for 循环:当需要按顺序迭代数组的所有元素时,普通 for 循环是最好的选择。它简单直接,性能也较好。
1
2
3
4
var array = [1, 2, 3];
for (var i = 0; i < array.length; i++) {
console.log(array[i]);
}
  • 使用 for...of 循环(ES6 及以上)for...of 循环专门用于迭代可迭代对象,如数组。它会忽略原型链上的属性,并且按顺序迭代数组元素。
1
2
3
4
var array = [1, 2, 3];
for (var item of array) {
console.log(item);
}
  • 使用 forEach 方法forEach 方法是数组的一个内置方法,它会对数组的每个元素执行一次提供的函数。
1
2
3
4
var array = [1, 2, 3];
array.forEach(function(item) {
console.log(item);
});

常见问题

1. for...in 会遍历继承属性

如果数组原型被修改,for...in 会遍历这些继承的属性。可以使用 hasOwnProperty 方法来过滤继承属性,但这增加了代码的复杂度。

2. 迭代顺序不保证

for...in 循环的迭代顺序是不保证的,这可能导致在需要按顺序处理数组元素时出现问题。

3. 性能问题

for...in 循环需要遍历对象的所有属性,包括原型链上的属性,这可能会导致性能下降。尤其是在处理大型数组时,性能问题会更加明显。

4. 索引类型问题

for...in 循环中的索引是字符串类型,而不是数字类型。这可能会导致在进行数学运算时出现意外的结果。例如:

1
2
3
4
var a = [1, 2, 3];
for (var i in a) {
console.log(typeof i); // 输出: string
}

综上所述,虽然 for...in 循环在某些情况下可以使用,但在迭代数组时,最好使用其他更合适的方法,以避免潜在的问题。


为何使用 'for...in' 迭代数组不是个好主意?
https://119291.xyz/posts/why-is-using-for-in-for-array-iteration-a-bad-idea/
作者
ww
发布于
2025年5月22日
许可协议