介绍 (Introduction)
Reduce is a method that can be difficult to understand especially with all the vague explanations that can be found on the web. There are a lot of benefits to understanding reduce
as it is often used in state management (think Redux).
减少是一种很难理解的方法,尤其是在网上可以找到所有含糊的解释的情况下。 了解reduce
会带来很多好处,因为它通常用于状态管理中(请考虑Redux )。
The signature for the reduce
array method in JavaScript is:
JavaScript中reduce
数组方法的签名为:
arr.reduce(callback, initialValue);
术语 (Terminology)
Reduce comes with some terminology such as reducer & accumulator. The accumulator
is the value that we end with and the reducer
is what action we will perform in order to get to one value.
Reduce带有减速器和累加器等术语。 accumulator
是我们最终的价值,而reducer
是我们为了达到一个价值而将要采取的行动。
You must remember that a reducer will only return one value and one value only hence the name reduce.
您必须记住, reducer只返回一个值,而仅返回一个值,因此名称为reduce 。
Take the following classic example:
以以下经典示例为例:
const value = 0;
const numbers = [5, 10, 15];
for(let i = 0; i < numbers.length; i++) {
value += numbers[i];
}
The above will give us 30
(5 + 10 + 15). This works just fine, but we can do this with reduce
instead which will save us from mutating our value
variable.
以上将给我们30
(5 + 10 + 15)。 这很好用,但是我们可以使用reduce
来代替,这可以避免我们改变我们的value
变量。
The below code will also output 30
, but will not mutate our value
variable (which we have now called initialValue
)
下面的代码也将输出30
,但不会改变我们的value
变量(我们现在将其称为initialValue
)
/* this is our initial value i.e. the starting point*/
const initialValue = 0;
/* numbers array */
const numbers = [5, 10, 15];
/* reducer method that takes in the accumulator and next item */
const reducer = (accumulator, item) => {
return accumulator + item;
};
/* we give the reduce method our reducer function
and our initial value */
const total = numbers.reduce(reducer, initialValue)
The above code may look a little confusing, but under the hood there is no magic going on. Let’s add a console.log
in our reducer
method that will output the accumulator
and the item
arguments.
上面的代码可能看起来有些混乱,但是在幕后并没有发生任何魔术。 让我们在我们的reducer
方法中添加一个console.log
,它将输出accumulator
和item
参数。
The following screenshot shows what’s logged to the console:
以下屏幕快照显示了记录到控制台的内容:

So the first thing we notice is our method is called 3
times because there are 3
values in our array. Our accumulator begins at 0
which is our initialValue
we passed to reduce
. On each call to the function the item
is added to the accumulator
. The final call to the method has the accumulator
value of 15
and item
is 15
, 15 + 15
gives us 30
which is our final value. Remember the reducer
method returns the accumulator
plus the item
.
因此,我们注意到的第一件事是我们的方法被调用了3
次,因为数组中有3
值。 我们的累加器从0
开始,这是我们传递给reduce
initialValue
。 在每次调用该函数时,该item
都会添加到accumulator
。 该方法的最终调用具有15
的accumulator
值,而item
为15
,则15 + 15
给出的最终值为30
。 请记住, reducer
方法返回accumulator
加上item
。
So that is a simple example of how you would use reduce
, now let’s dive into more a complicated example.
因此,这是一个如何使用reduce
的简单示例,现在让我们进入一个更复杂的示例。
使用Reduce展平数组 (Flattening an Array Using Reduce)
Let’s say we have the following array:
假设我们有以下数组:
const numArray = [1, 2, [3, 10, [11, 12]], [1, 2, [3, 4]], 5, 6];
And let’s say for some crazy reason, JavaScript has removed the .flat
method so we have to flatten this array ourselves.
出于某种疯狂的原因,我们说JavaScript删除了.flat
方法,因此我们必须自己对此数组进行展平。
So we’ll write a function to flatten any array no matter how deeply nested the arrays are:
因此,无论数组嵌套的深度如何,我们都会编写一个函数来展平任何数组:
function flattenArray(data) {
// our initial value this time is a blank array
const initialValue = [];
// call reduce on our data
return data.reduce((total, value) => {
// if the value is an array then recursively call reduce
// if the value is not an array then just concat our value
return total.concat(Array.isArray(value) ? flattenArray(value) : value);
}, initialValue);
}
If we pass our numArray
to this method and log the result we get the following:
如果将numArray
传递给此方法并记录结果, numArray
得到以下结果:

This is a great example on how we can make a very common operation quite simple.
这是一个很好的例子,说明了如何使非常常见的操作变得非常简单。
Let’s go over one more example.
让我们再看一个例子。
最后的示例-更改对象结构 (Final Example - Changing an Object Structure)
So with the new Pokemon game coming out, let’s pretend we have a server that sends us an array of Pokemon objects like so:
因此,随着新的Pokemon游戏发布,我们假设我们有一个服务器向我们发送了一系列Pokemon对象,如下所示:
const pokemon = [
{ name: "charmander", type: "fire" },
{ name: "squirtle", type: "water" },
{ name: "bulbasaur", type: "grass" }
]
We want to change this object to look like:
我们想要将此对象更改为以下形式:
const pokemonModified = {
charmander: { type: "fire" },
squirtle: { type: "water" },
bulbasaur: { type: "grass" }
};
To get to that desired output we do the following:
为了获得所需的输出,我们执行以下操作:
const getMapFromArray = data =>
data.reduce((acc, item) => {
// add object key to our object i.e. charmander: { type: 'water' }
acc[item.name] = { type: item.type };
return acc;
}, {});
If we call our method like so:
如果我们这样调用我们的方法:
getMapFromArray(pokemon)
We get our desired output:
我们得到所需的输出:

You can check out the Codesandbox here.
您可以在此处签出Codesandbox 。
结论 (Conclusion)
At first sight, the reduce
looks more complex than other JavaScript Array Iteration Methods like map
and filter
, but once the syntax, core concepts and use-cases are understood it can be another powerful tool for JavaScript developers.
乍一看,与其他JavaScript数组迭代方法(例如map
和filter
相比, reduce
看起来更复杂,但是一旦了解了语法,核心概念和用例,它就可以成为JavaScript开发人员的另一个强大工具。
翻译自: https://www.digitalocean.com/community/tutorials/js-finally-understand-reduce