- Published on
JavaScript 中迭代数组的多种方式
- Authors
- Name
在 JavaScript 中,有多种方法可以用来循环遍历数组。本文将介绍这些方法,包括 for-of
循环、forEach
方法、传统的 for
循环以及其他不常见的方式,同时探讨它们在处理异步操作时的不同表现。
快速总结
最常用的几种方式:
for-of
循环 (仅限 ES2015+)
* 它简单易用,并且
async
友好。for (const element of theArray) { // 使用 element 变量 }
forEach
方法 (仅限 ES5+)
* 它非常适合同步操作,但不支持异步操作。
theArray.forEach((element) => { // 使用 element 变量 })
for
循环
* 传统的 虽然较为老旧,但它支持异步操作。
for (let index = 0; index < theArray.length; index++) { const element = theArray[index] // 使用 element 变量 }
for-in
循环
* 使用小心的 它同样支持异步操作,但不建议用于数组循环。
for (const propertyName in theArray) { if (theArray.hasOwnProperty(propertyName)) { const element = theArray[propertyName] // 使用 element 变量 } }
不推荐的几种方式:
- 不要使用
for-in
,除非你能够确保用适当的保障措施或清楚其可能引发的问题。 - 不要使用
map
方法,如果你不需要它的返回值。map
方法是用来生成一个新数组的,而不是为了简单地遍历一个数组。 - 不要使用
forEach
,如果你的回调函数包含异步操作,并且你希望forEach
等待这些操作完成(因为它不会等)。
接下来,我们将深入探讨各种循环方法的具体用法和特点。
针对真正的数组
for-of
循环 (仅限 ES2015+)
1. 使用 for-of
循环是 ES2015 添加的一种基于迭代器的循环方式。数组是可迭代对象,因此可以使用 for-of
循环进行遍历:
const a = ['a', 'b', 'c']
for (const element of a) {
console.log(element)
}
// 输出:a
// b
// c
for-of
循环简洁明了,并且是 async
友好的:
async function processArray(array) {
for (const element of array) {
await someAsyncFunction(element)
}
}
forEach
方法 (仅限 ES5+)
2. 使用 forEach
方法在 ES5 中引入,它适用于同步代码,不适用于异步操作:
const a = ['a', 'b', 'c']
a.forEach((element) => {
console.log(element)
})
需要注意的是,forEach
不等待异步回调完成:
a.forEach(async (element) => {
await someAsyncFunction(element)
console.log(element)
})
上面的代码不会按顺序执行异步操作。
for
循环
3. 使用传统的 传统的 for
循环既支持同步也支持异步操作:
const a = ['a', 'b', 'c']
for (let index = 0; index < a.length; index++) {
const element = a[index]
console.log(element)
}
在异步环境中:
async function processArray(array) {
for (let index = 0; index < array.length; index++) {
await someAsyncFunction(array[index])
}
}
for-in
循环(慎用)
4. 使用 使用 for-in
循环遍历数组时需慎重,因为它会遍历对象的所有可枚举属性,包括继承属性:
const a = ['a', 'b', 'c']
for (const key in a) {
if (a.hasOwnProperty(key)) {
const element = a[key]
console.log(element)
}
}
5. 显式使用迭代器 (仅限 ES2015+)
有时你可能需要显式使用迭代器:
const a = ['a', 'b', 'c']
const iterator = a.values()
let result = iterator.next()
while (!result.done) {
console.log(result.value)
result = iterator.next()
}
这种方式在异步环境中特别有用:
async function processArray(array) {
const iterator = array.values()
let result = iterator.next()
while (!result.done) {
await someAsyncFunction(result.value)
result = iterator.next()
}
}
针对类数组对象
除了真正的数组,JavaScript 也有类数组对象,如 NodeList
实例,HTMLCollection
实例,arguments
对象等。
使用大部分上述选项
现代浏览器中大部分数组的循环方法对类数组对象都适用:
使用
for-of
循环 (仅限 ES2015+)const nodes = document.querySelectorAll('div') for (const node of nodes) { console.log(node) }
使用
forEach
方法 (仅限 ES5+)const nodes = document.querySelectorAll('div') Array.prototype.forEach.call(nodes, (node) => { console.log(node) })
使用传统的
for
循环const nodes = document.querySelectorAll('div') for (let i = 0; i < nodes.length; i++) { console.log(nodes[i]) }
转换为真正的数组
有时你可能希望将类数组对象转换为真正的数组,可以使用以下方法:
使用
Array.from
(仅限 ES2015+)const nodesArray = Array.from(document.querySelectorAll('div'))
使用展开语法 (仅限 ES2015+)
const nodesArray = [...document.querySelectorAll('div')]
使用
Array.prototype.slice.call
const nodesArray = Array.prototype.slice.call(document.querySelectorAll('div'))
总结
JavaScript 提供了多种方法来循环遍历数组和类数组对象,每种方法有其特定的适用场景和优缺点。在选择具体方法时,应根据需要考虑同步或异步操作的要求,以及代码的可读性和执行效率。