在 JavaScript 中有几种方法可以遍历数组,关于哪种方法是正确的方法存在很多争论。 一般来说,有4种常见的模式:
- 简单的
for
循环:for (let i = 0; i < arr.length; ++i)
- 函数方法如
forEach()
:arr.forEach((v, i) => { /* ... */ })
- for-of 循环:
for (const v of arr)
- for-in 循环:
for (const i in arr)
以下是 4 种常见方法之间的几个最重要的区别。
TLDR: 尽可能使用 for-of (3)。 简单的 for
循环(1)也可以。 不要 _ 使用 for/in
。
异步/等待 支持
具有功能方法的大问题,例如 forEach()
就是这样,因为您将一个单独的函数传递给 forEach()
,使用 async/await forEach()
很难 。例如,下面的代码将以相反的顺序打印数字 0-9,因为 forEach()
并行执行异步函数,并没有给你处理错误的方法。
async function print(n) {
// Wait 1 second before printing 0, 0.9 seconds before printing 1, etc.
await new Promise(resolve => setTimeout(() => resolve(), 1000 - n * 100));
// Will usually print 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 but order is not strictly
// guaranteed.
console.log(n);
}
async function test() {
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9].forEach(print);
}
test();
另一方面,异步函数与 JavaScript 的内置循环配合得很好。
async function print(n) {
await new Promise(resolve => setTimeout(() => resolve(), 1000 - n * 100));
console.log(n);
}
async function test() {
// Prints 0-9 in order.
for (const num of [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]) {
await print(num);
}
}
test();
非数字属性
JavaScript 数组是对象。 typeof [] === object
,这意味着数组可以具有非数字属性。 避免使用的主要原因 for/in
就是它 for/in
迭代非数字属性,而 for
、forEach()
, 和 for/of
跳过非数字属性。
const arr = [a, b, c];
arr[bad] = alpha;
for (let key in arr) {
console.log(arr[key]); // Prints: a, b, c, alpha
}
// However, `for/of` skips non-numeric keys
for (const val of arr) {
console.log(val); // Prints: a, b, c
}
// So does `forEach()`
arr.forEach(val => console.log(val)); // Prints: a, b, c
const
迭代器键
使用简单时的一个常见错误 for
循环无意中增加 i
,我已经记不清有多少次我不小心在嵌套中增加了错误的计数器 for
循环。
for (let i = 0; i < arr.length; ++i) {
// So easy to accidentally type `++i` below.
for (let j = 0; j < arr.length; ++i) {
}
}
forEach()
、for/of
和 for/in
具有能够通过意外修改循环索引来防止弄乱循环的好处。你可以修改 index
参数,但这对循环没有影响。 for/of
和 for/each
,您可以将迭代器键标记为 const
。
for (const [i, el] of Object.entries(arr)) {
++i; // Compile time error
}
概括
下面是比较循环结构的图表:
你应该更喜欢使用 for/of
除非你有充分的理由不这样做。 您可能想使用 forEach()
对于一些整洁的语法糖 filter()
和 map()
,或者您可能实际上想要遍历数组上的非数字属性并使用 for/in
,但 for/of
是最稳健的方法,几乎适用于所有情况。
请登录后查看评论内容