如何在 JavaScript 中执行常见的操作,其中可能使用循环,使用 map()、filter()、reduce() 和 find()

循环通常用于在任何编程语言中对数组执行操作:给定一个数组,您可以迭代其元素并执行计算。

让我们看看如何选择常见需求并使用**函数式编程**方法执行它们,而不使用循环。

注意:我不推荐其中一种方法。我只是想介绍执行相同操作的不同方式,并可能向您介绍一些以前可能从未使用过的新函数。

mapfilterreducefind

这些是三个非常强大的数组函数:

  • map 返回一个与原始数组具有相同长度的数组。
  • filter 如其名所示,返回比原始数组少的项目的数组。
  • reduce 返回一个单个值(或对象)。
  • find 返回数组中满足条件的第一个项目。

mapfilterreduce 在 ES5 中引入,因此您可以安全地在每个浏览器中使用它们的实现已经多年了。

find 在 ES6/ES2015 中引入。

它们提供了一种更加声明性的方法,而不是命令性的方法(描述应该发生的情况,而不是写出应该发生的每个微小处理)。

使用 map 在每个元素上执行某些操作

使用循环的示例如下:

const performSomething = (item) => {
    // ...
    return item;
};
const items = ['a', 'b', 'c'];
items.forEach((item) => {
    performSomething(item);
});

使用声明性方法,您告诉 JavaScript 在每个元素上执行某些操作:

const items = ['a', 'b', 'c'];
const newArray = items.map((item) => performSomething(item));

这将生成一个新数组,而不是编辑原始数组(我们称之为不可变性)。

由于在 map 回调函数中使用了单个函数,我们可以将示例重写为:

const items = ['a', 'b', 'c'];
const newArray = items.map(performSomething);

在数组中查找单个元素

有时您需要在数组中查找特定的项目并返回它。

使用循环可以这样做:

const items = [
    { name: 'a', content: { /* ... */ }},
    { name: 'b', content: { /* ... */ }},
    { name: 'c', content: { /* ... */ }}
];
for (const item of items) {
    if (item.name === 'b') {
        return item;
    }
}

这是使用 find()(ES6+)的非循环版本:

const b = items.find((item) => item.name === 'b');

这是使用 filter()(ES5+)的相同功能:

const b = items.filter((item) => item.name === 'b').shift();

shift() 返回数组中的第一个项目,如果数组为空则不会引发错误(在这种情况下返回 undefined)。

注意:shift() 会改变数组,但它改变的是由 filter() 返回的数组,而不是原始数组。如果这听起来不可接受,您可以检查数组是否不为空,并使用 b[0] 获取第一个项目。

出于学习目的(实际上没有太多意义),以下是使用 reduce() 实现相同功能:

const items = [
    { name: 'a', content: { /* ... */ }},
    { name: 'b', content: { /* ... */ }},
    { name: 'c', content: { /* ... */ }}
];

const b = items.reduce((result, item) => {
    if (item.name === 'b') { result = item; }
    return result;
}, null);

filter()reduce() 将遍历所有数组项,而 find() 将更快一些。

遍历数组以计算每个项目的属性计数

使用 reduce() 从数组中获取单个值。例如,对项的 content.value 属性求和:

const items = [
    { name: 'a', content: { value: 1 }},
    { name: 'b', content: { value: 2 }},
    { name: 'c', content: { value: 3 }}
];

使用循环:

let count = 0;
for (const item of items) {
    count += item.content.value;
}

可以写为:

const count = items.reduce((result, { content: { value } }) => result + value, 0);