Javascript
功能性编程
forEach()

Javascript forEach()方法: examples, index, map, break continue return

当你需要在JavaScript中使用数组和循环时。最常用的方法之一是forEach()方法。 在这篇文章中,我们将看看使用forEach()方法的例子,indexarray参数、 它与其他方法如map()有什么不同,以及如何使用break``continue{:js}``return{:js}等关键字。

forEach()方法不仅为数组实现,也为大多数JavaScript数据类型,如集合和地图实现。 这次我们只看数组的方法。

💡

要运行Node.js,我建议[用asdf安装](/js/env/asdf-nodejs)。你可以在这篇文章中阅读更多关于这个问题的内容。

1. JavaScript forEach() 基础知识

1.1. 了解Array.prototype.forEach()方法

forEach方法是Array.prototype对象的一部分,所以它对所有数组实例都可用。 这个方法提供了一种可读的方式来遍历一个数组并对每个元素执行指定的函数。 forEach()方法接收一个回调函数作为参数, 它对数组中的每个元素执行回调。

1.2. forEach()方法的基本语法

使用forEach()方法的基本语法很简单。

array.forEach(function callback(currentValue[, index[, array]]) {
    // Your code here
})

这个回调函数需要三个参数:当前值、索引和数组。 currentValue代表数组中的当前元素,index代表其位置,array是数组本身的引用、 参数indexarray是可选的。

下面是一个使用简单的forEach()方法的例子。

const numbers = [1, 2, 3, 4, 5];
numbers.forEach(number => console.log(number));

1.3. 与常规for语句相比

与传统的for语句相比,forEach()方法提供了一个更可读和简洁的语法。 它还可以防止开发者的错误,如索引外迭代或数组值被修改,造成错误。

然而,forEach在使用时应该注意,它不能提供与for语句相同的控制水平,特别是在脱离迭代或跳过迭代时。

2. forEach(), map()差异

在JavaScript中可用于迭代数组的其他方法包括filter(), map(), 和reduce()。 这些方法比forEach更专业,并针对特定的使用情况进行了优化:

  • map():通过对每个元素应用回调函数来转换数组,并返回一个包含转换后的元素的新数组。
  • Reduce():通过应用一个函数将数组中的值与当前值相结合,将数组中的值减少到一个单一的值。
  • filter(): 创建一个新的数组,只保留那些符合指定条件的元素。

注意,map()方法返回一个新数组,而forEach()方法总是返回undefined

关于其他数组方法的更多信息,请看它们各自的文章。

3.forEach()方法中的break, continue, return关键字

基于函数式编程的forEach()方法的基本前提是遍历数组的所有元素。 因此,它不支持使用breakcontinue关键字来暂停或恢复遍历。

然而,你可以使用return关键字来取代break关键字的作用。

在下面的例子中,当元素值为3时,你可以看到return关键字被用来中断到下一个元素。

const array = [1, 2, 3, 4, 5];
 
array.forEach((element) => {
  if (element === 3) {
    return; // Skips the current iteration
  }
 
  console.log(element);
});

4. 使用forEach()的例子

4.1. 清理和格式化数据

JavaScript forEach()方法可以在处理或显示数据之前对其进行清理和格式化。 例如,假设你有一个混合大小写名字的用户对象数组。

你可以使用forEach()方法来规范大小写:

const users = [
    { id: 1, name: "ALICE" },
    { id: 2, name: "BOb" },
    { id: 3, name: "Charlie" }
];
 
users.forEach((user) => {
    user.name =
    user.name.charAt(0).toUpperCase() + user.name.slice(1).toLowerCase();
});
 
console.log(users);
 
// Output:
// [
//   { id: 1, name: 'Alice' },
//   { id: 2, name: 'Bob' },
//   { id: 3, name: 'Charlie' }
// ]

在这个例子中,forEach()方法遍历users数组,将每个用户的名字改为适当的大写。 这种类型的数据组织有助于确保整个应用程序的一致性,使数据更容易查看和操作。

4.2. 操纵DOM

forEach()方法使得迭代HTML集合以操作DOM元素变得容易。 例如,你可能想给所有具有特定类名的元素添加一个类:

const elements = document.getElementsByClassName("target");
 
Array.prototype.forEach.call(elements, (element) => {
    element.classList.add("new-class");
});

它也可以用来改变DOM元素的属性或内容。 例如,如果你想改变所有具有某个类别名称的image元素的src属性,你可以这样做

const images = document.querySelectorAll(".image-class");
 
images.forEach((image) => {
    image.src = "new-image-source.jpg";
});

4.3. 将forEach与其他数组方法串联起来

你可以将forEach()方法与其他数组方法串联起来,以创建更强大和可读的代码。 例如,假设你有一个订单数组,你想计算某个特定产品的订单的总收入:

const orders = [
    { id: 1, product: "A", price: 10, quantity: 2 },
    { id: 2, product: "B", price: 20, quantity: 1 },
    { id: 3, product: "A", price: 10, quantity: 3 },
    { id: 4, product: "C", price: 30, quantity: 1 }
];
 
const targetProduct = "A";
 
const totalRevenue = orders
    .filter((order) => order.product === targetProduct)
    .map((order) => order.price * order.quantity)
    .reduce((acc, curr) => acc + curr, 0);
 
console.log(totalRevenue);

在这个例子中,我们首先过滤订单数组,只保留那些包含目标产品的订单。 然后,它使用map方法来计算每个过滤后的订单的收入。 最后,它使用reduce方法累积总收入。 这种链式方法导致了更多的可读性和功能性代码,这使得代码更容易理解和维护。

5. 在回调函数中使用索引、数组参数

forEach()方法的回调函数不仅提供了访问当前值的引用,还提供了访问每个索引和数组本身的引用。 这使得你可以定义一个更灵活的回调函数。

const numbers = [10, 20, 30, 40, 50];
 
numbers.forEach((number, index, array) => {
    console.log(`Index: ${index}, Number: ${number}, Array: ${array}`);
});
 
// Output:
// Index: 0, Number: 10, Array: 10,20,30,40,50
// Index: 1, Number: 20, Array: 10,20,30,40,50
// Index: 2, Number: 30, Array: 10,20,30,40,50
// Index: 3, Number: 40, Array: 10,20,30,40,50
// Index: 4, Number: 50, Array: 10,20,30,40,50

6. 实现一个自定义的forEach方法

在某些情况下,你可能想扩展forEach的功能以满足你的需要。 例如,你可能想创建一个自定义的forEach函数来快速退出循环,比如从一个for语句中退出break,或者为一个回调函数提供额外的参数。

要创建一个自定义forEach函数,你可以使用for语句并传递任何你想要的参数。 下面是一个带有break函数的自定义forEach函数的例子:

function customForEach(array, callback) {
    for (let i = 0; i < array.length; i++) {
        const result = callback(array[i], i, array);
        if (result === false)
            break;
    }
}
 
const numbers = [1, 2, 3, 4, 5];
 
customForEach(numbers, (number) => {
    if (number > 3) return false; // "break" when number > 3
        console.log(number);
});
 
// Output:
// 1
// 2
// 3

7. 总结

在这篇文章中,我们介绍了一个使用forEach()方法的例子,它与其他方法如indexarray参数、map()有什么区别、 使用break, continue, return关键字,等等。

通过了解forEach()方法的优点和局限性,让你写出更干净、更高效的代码,你将更好地应对各种网络开发挑战。 我鼓励你继续探索forEach()和其他数组方法,以提高你的JavaScript技能,创建更有效、更吸引人的网络应用。

copyright for Javascript foreach

© 2023 All rights reserved.