原文: JavaScript forEach() – JS Array For Each Loop Example

在使用数组时,有时需要循环或遍历数组的值,以便输出或操作它们。

这些数组可以保存各种数据类型,包括对象、数字、字符串等。

本文将介绍如何使用 JavaScript forEach() 数组方法来遍历各种类型的数组,以及它与 for 循环方法的区别。

JavaScript 中有许多迭代方法,包括 forEach() 方法,它们几乎都执行相同的功能,只是略有不同。是否使用特定的循环方法完全取决于你自己,但重要的是我们要了解每种循环方法及其工作原理。

JavaScript forEach()

forEach() 数组方法对任意数组进行循环,对每个数组元素按升序索引顺序执行一次所提供的函数。该函数被称为回调函数。

注:数组是元素的集合,元素可以是任何数据类型。

forEach() 循环的语法和参数

以下是 forEach 循环的标准写法:

array.forEach(callbackFunction);
array.forEach(callbackFunction, thisValue);

回调函数最多可接受三个不同的参数,但并非所有参数都是必需的。下面是一些使用普通函数和 ES6 方法声明回调函数的 forEach() 循环示例:

// 只使用当前元素
array.forEach((currentElement) => { /* ... */ })
array.forEach(function(currentElement) { /* ... */ })

// 只使用当前元素和索引值
array.forEach((currentElement, index) => { /* ... */ })
array.forEach(function(currentElement, index) { /* ... */ })

// 只使用当前元素、当前元素的索引值和当前元素所属的数组对象
array.forEach((currentElement, index, array) => { /* ... */ })
array.forEach(function(currentElement, index, array){ /* ... */ })

// 使用所有参数和 thisValue(回调中 this 的值)
array.forEach((currentElement, index, array) => { /* ... */ }, thisValue)
array.forEach(function(currentElement, index, array) { /* ... */ }, thisValue)

上面的语法可能看起来有些混乱,但这是编写 forEach 循环的一般语法,具体取决于要使用的值。让我们来看看我们使用的所有参数:

1、callbackFunction:回调函数是一个对每个元素只执行一次的函数,可以接受以下参数用于回调函数中:

  • currentElement:顾名思义,当前元素就是循环发生时数组中正在处理的元素。这是唯一必需的参数。
  • index:这是一个可选参数,指的是 currentElement 的索引。
  • array:这是一个可选参数,用于返回传递给 forEach() 方法的数组。

2、thisValue:这是一个可选参数,用于指定将在回调函数中使用的值。

总之,forEach() 数组迭代方法接受一个回调函数,该回调函数有可在回调函数中用于每个数组项的参数,如数组项、项的索引和整个数组。

JavaScript forEach() 示例

在了解其他可能的示例之前,我们先看看传入回调函数的所有参数及其用途。

如何使用 currentElement 参数

假设我们有一个雇员详细信息数组,其中包括姓名、年龄、工资金额和货币:

const staffsDetails = [
  { name: "Jam Josh", age: 44, salary: 4000, currency: "USD" },
  { name: "Justina Kap", age: 34, salary: 3000, currency: "USD" },
  { name: "Chris Colt", age: 37, salary: 3700, currency: "USD" },
  { name: "Jane Doe", age: 24, salary: 4200, currency: "USD" }
];

如果我们想单独显示所有名字,并在名字周围加上一些词语,我们可以使用 forEach() 方法,具体如下:

staffsDetails.forEach((staffDetail) => {
  let sentence = `I am ${staffDetail.name} a staff of Royal Suites.`;
  console.log(sentence);
});

输出:

"I am Jam Josh a staff of Royal Suites."
"I am Justina Kap a staff of Royal Suites."
"I am Chris Colt a staff of Royal Suites."
"I am Jane Doe a staff of Royal Suites."

注:如果 currentElement 值是一个包含键/值对的对象,我们也可以通过这种方式对其进行解构:

staffsDetails.forEach(({ name }, index) => {
  let sentence = `I am ${name} a staff of Royal Suites.`;
  console.log(sentence);
});

如何使用 index 参数

我们也可以这样使用未构建的 index 参数来获取每个数组项的索引:

staffsDetails.forEach((staffDetail, index) => {
  let sentence = `index ${index} : I am ${staffDetail.name} a staff of Royal Suites.`;
  console.log(sentence);
});

输出:

"index 0 : I am Jam Josh a staff of Royal Suites."
"index 1 : I am Justina Kap a staff of Royal Suites."
"index 2 : I am Chris Colt a staff of Royal Suites."
"index 3 : I am Jane Doe a staff of Royal Suites."

如何使用 array 参数

array 参数是第三个参数,用于保存正在迭代的原始数组。例如,我们可以尝试这样在控制台中显示数值:

staffsDetails.forEach((staffDetail, index, array) => {
  console.log(array);
});

这将输出整个数组 4 次,因为我们有 4 个项,迭代运行 4 次。让我们对一个只有几个值的数组进行迭代,这样我就可以在这里添加输出结果了:

let scores = [12, 55, 70];

scores.forEach((score, index, array) => {
  console.log(array);
});

输出:

[12,55,70]
[12,55,70]
[12,55,70]

到目前为止,我们已经使用了回调函数的所有参数。在与 for 循环方法进行快速比较之前,让我们看看其他一些示例,以充分了解它是如何工作的。

如何使用 forEach() 将数字数组中的所有值相加

假设我们有一个 scores 数组。我们可以使用 forEach() 数组方法来循环并将这些数字相加:

const scores = [12, 55, 70, 47];

let total = 0;
scores.forEach((score) => {
  total += score;
});

console.log(total);

回想一下,前面我们使用的是员工详细信息数组。现在,让我们尝试将所有员工的工资加在一起,看看如何使用对象:

let totalSalary = 0;
staffsDetails.forEach(({salary}) => {
  totalSalary += salary;
});

console.log(totalSalary + " USD"); // "14900 USD"

我们解构了 currentElement 对象。

如何在 forEach() 回调函数中使用条件

在遍历数组时,我们可能需要检查特定条件,这通常与 for 循环方法相同。我们可以将这些条件传递到回调函数中,或者传递到我们想在每个数组项上运行的任何其他操作中。

例如,如果我们只想从之前声明的员工详细信息数组中显示工资大于或等于 4000 的人员姓名,可以执行以下操作:

staffsDetails.forEach(({name, salary}) => {
  if(salary >= 4000){
    console.log(name);
  }
});

输出:

"Jam Josh"
"Jane Doe"

比较 forEach() 和 for 循环

for 循环与 forEach 方法非常相似,但各自都有一些独特的功能,例如:

跳出和继续循环

在循环遍历数组时,我们可能希望在满足特定条件时跳出或继续循环。这可以通过 breakcontinue 指令来实现,但在 forEach() 方法中却行不通,如下图所示:

const scores = [12, 55, 70, 47];

scores.forEach((score) => {
  console.log(score);

  if (score === 70) 
    break;
});

这将产生 Illegal break statement 的语法错误。continue 指令也是这样,它也会产生 Illegal continue statement: no surrounding iteration statement

const scores = [12, 55, 70, 47];

scores.forEach((score) => {
  if (score === 70) 
    continue;
  
  console.log(score);
});

但幸运的是,这与 for 循环方法配合得天衣无缝:

const scores = [12, 55, 70, 47];

for (i = 0; i < scores.length; i++) {
  console.log(scores[i]);

  if (scores[i] === 70) 
    break;
}

输出:

12
55
70

continue 指令也是如此:

const scores = [12, 55, 70, 47];

for (i = 0; i < scores.length; i++) {
  if (scores[i] === 70) 
    continue;
  
  console.log(scores[i]);
}

输出:

12
55
47

元素缺失的数组

另一个需要进行比较的重要情况是,我们正在迭代的数组有一些缺失值/数组项,如下所示:

const studentsScores = [70, , 12, 55, , 70, 47];

这可能是由于开发人员的错误或其他原因造成的,但这两种方法采用了两种不同的方式来循环这些类型的数组。如果存在缺失值,for 循环会返回 undefined,而 forEach() 方法则会跳过缺失值。

For 循环

const studentsScores = [70, , 12, 55, , 70, 47];

for (i = 0; i < studentsScores.length; i++) {
  console.log(studentsScores[i]);
}

输出:

70
undefined
12
55
undefined
70
47

forEach()

const studentsScores = [70, , 12, 55, , 70, 47];

studentsScores.forEach((stundentScore) => {
  console.log(stundentScore);
});

输出:

70
12
55
70
47

Async/Await 对 forEach() 数组方法无效,但对 for 循环方法有效。

总结

在本文中,我们学习了如何使用 forEach() 数组方法,该方法允许我们遍历包含任何类型项的数组。与 for 循环相比,它还能让我们写出更简洁、更易读的代码。