JavaScript中数组循环(for each)的方法

JavaScript中数组循环(for each)的方法

JavaScript 提供了多种强大的语义来遍历数组和类数组对象。本文将分别介绍针对真实数组和类数组对象的循环方法。

技术背景

在 JavaScript 编程中,经常需要对数组进行遍历操作,以处理数组中的每个元素。不同的循环方法适用于不同的场景,例如同步或异步操作、稀疏数组处理等。了解这些方法的特点和使用场景,有助于编写更高效、更清晰的代码。

实现步骤

针对真实数组

  • 使用 for-of(隐式使用迭代器,ES2015+):ES2015 为 JavaScript 添加了迭代器和可迭代对象的概念,数组是可迭代对象。for-of 语句可以遍历迭代器返回的值。
1
2
3
4
const a = ["a", "b", "c"];
for (const element of a) {
console.log(element);
}
  • 使用 forEach 及相关方法(ES5+):在支持 ES5 的环境中,可以使用 forEach 方法处理同步代码。该方法接受一个回调函数,会为数组中的每个元素依次调用该回调函数。
1
2
3
4
const a = ["a", "b", "c"];
a.forEach((element) => {
console.log(element);
});

ES5 还定义了其他一些有用的数组方法,如 everysomefiltermapreducereduceRight

  • 使用简单的 for 循环:这是一种传统的循环方式,通过控制索引来遍历数组。
1
2
3
4
5
const a = ["a", "b", "c"];
for (let index = 0; index < a.length; ++index) {
const element = a[index];
console.log(element);
}

在性能敏感的代码中,可以提前获取数组长度,以提高性能。

1
2
3
4
5
const a = ["a", "b", "c"];
for (let index = 0, len = a.length; index < len; ++index) {
const element = a[index];
console.log(element);
}

也可以反向遍历数组。

1
2
3
4
5
const a = ["a", "b", "c"];
for (let index = a.length - 1; index >= 0; --index) {
const element = a[index];
console.log(element);
}
  • 正确使用 for-infor-in 主要用于遍历对象的属性,而不是数组。但在处理稀疏数组或需要遍历数组对象的非元素属性时,可以使用 for-in,但需要添加适当的检查。
1
2
3
4
5
6
7
8
9
10
const a = [];
a[0] = "a";
a[10] = "b";
a[10000] = "c";
for (const name in a) {
if (Object.hasOwn(a, name) && /^0$|^[1-9]\d*$/.test(name) && name <= 4294967294) {
const element = a[name];
console.log(a[name]);
}
}
  • 显式使用迭代器(ES2015+)for-of 隐式使用迭代器,也可以显式使用迭代器来遍历数组。
1
2
3
4
5
6
7
const a = ["a", "b", "c"];
const it = a.values();
let entry;
while (!(entry = it.next()).done) {
const element = entry.value;
console.log(element);
}

针对类数组对象

类数组对象具有 length 属性和以数字命名的属性,如 NodeListHTMLCollectionarguments 对象等。

  • 使用上述大部分方法
    • 使用 for-of(ES2015+):许多类数组对象支持迭代,可以使用 for-of 进行遍历。
1
2
3
4
const divs = document.querySelectorAll("div");
for (const div of divs) {
div.textContent = Math.random();
}
- **使用 `forEach` 及相关方法(ES5+)**:可以通过 `Function#call` 或 `Function#apply` 将 `Array.prototype` 上的方法应用于类数组对象。
1
2
3
Array.prototype.forEach.call(node.childNodes, (child) => {
// Do something with child
});
- **使用简单的 `for` 循环**:简单的 `for` 循环同样适用于类数组对象。
- **显式使用迭代器(ES2015+)**:与数组类似,可以显式使用迭代器遍历类数组对象。
  • 创建真实数组
    • 使用 Array.fromArray.from 可以从类数组对象创建数组,还可以通过映射函数对元素进行转换。
1
const divs = Array.from(document.querySelectorAll("div"));
- **使用扩展语法 (`...`)**:ES2015 的扩展语法可以使用对象的迭代器将类数组对象转换为真实数组。
1
const divs = [...document.querySelectorAll("div")];
- **使用数组的 `slice` 方法**:可以使用 `Array.prototype.slice.call` 将类数组对象转换为真实数组。
1
const divs = Array.prototype.slice.call(document.querySelectorAll("div"));

最佳实践

  • 当处理异步操作时,优先使用 for-of 或简单的 for 循环,因为它们支持 async/await
  • 对于同步操作,forEach 是一个简洁的选择,但要注意它不支持 async/await
  • 处理稀疏数组时,可以考虑使用 for-in 并添加适当的检查。
  • 当需要对数组元素进行转换或过滤时,使用 mapfilter 等方法。

常见问题

  • for-in 的问题for-in 会遍历对象的所有可枚举属性,包括继承的属性,并且遍历顺序不固定。因此,除非有特殊需求,否则不建议使用 for-in 遍历数组。
  • forEach 与异步操作forEach 不支持 async/await,如果在回调函数中使用异步操作,forEach 不会等待异步操作完成就会继续执行。可以使用 for-of 或简单的 for 循环代替。
  • 旧浏览器兼容性问题:一些方法(如 for-offorEach 等)在旧浏览器中可能不支持,需要使用 polyfill 或采用其他兼容的方法。

JavaScript中数组循环(for each)的方法
https://119291.xyz/posts/2025-05-08.javascript-array-loop-methods/
作者
ww
发布于
2025年5月8日
许可协议