When I first started learning JavaScript, I had some trouble grasping reduce()
. I have heard of other people having trouble with it when they started as well. So I decided to write an overview of how it works hoping that it might help someone else.
What it does
reduce()
is a method that you can use with any array. It iterates over every element and returns one single result based on its operations. These operations depend on a parameter called reducer
, which is a callback function that we provide for the reduce()
method.
What on earth is 'a'?
The thing that really confused me about reduce()
was a
. But what is a
? If you look for examples of code using reduce()
online, you are likely to find things such as this.
const arr = [ 1, 2, 8, 14 ]
const sum = arr.reduce((a, b) => a + b)
I would look at stuff like that and tell myself, Okay, I understand that a
and b
are supposed to be elements in the array, but how on earth does JavaScript know which one is which? and how is the result of this that they all get added up? And that's an easy example. Then you see things like this one.
const arr = [["potatoes", 3], ["tomatoes", 85], ["onions", 27]]
const result = arr.reduce((a, b) => {
a[b[0]] = b[1]
return a
}, {})
Now, this is just bonkers. What on earth is that {}
as last parameter? What is this even doing?
Well, let's look at what this a
means (or any other argument name in that position, for that matter, it needn't be a
.) reduce()
's syntax is as follows:
arr.reduce(callback(accumulator, currentValue[, index[, array]])[, initial value])
Our callback function takes between two and four parametres.
-
accumulator
this is thea
in our previous examples. It is a variable wherereduce()
stores the result of each iteration over the array. -
currentValue
that's the name we'll use to call each element within the array. -
index
the index ofcurrentValue
(optional.) -
array
the whole array over which we are iterating (optional.)
The enlightening moment, for me, was realising that a
is the place where reduce()
stores the information of the previous iterations. So when we add stuff to it, we're keeping it safe until the end of the execution.
Let's analyse the first example
const arr = [ 1, 2, 8, 14 ]
const sum = arr.reduce((a, b) => a + b)
Here, our callback function adds up the current element with the accumulated value and that's what becomes the new accumulated value. Since there is no initial value passed as an argument, it will use the first element instead and skip running through it. So reduce()
will do the following:
-
a
= 1,b
= 2- 1 + 2 = 3
-
a
becomes 3
-
a
= 3,b
= 8- 3 + 8 = 11
-
a
becomes 11
-
a
= 11,b
= 14- 11 + 14 = 25
-
a
becomes 25
-
reduce()
returns 25, which is assigned as the value ofsum
.
Let's look at the second example
const arr = [["potatoes", 3], ["tomatoes", 85], ["onions", 27]]
const result = arr.reduce((a, b) => {
a[b[0]] = b[1]
return a
}, {})
This one is a bit more complex, because the operation isn't as simple and because we're initialising a
as an empty object. Our reducer function takes a two-dimensional array with sets of key
and value
and turns it into an object. Let's look at what is going on in more detail
-
a
is an empty object. -
a[b[0]] = b[1]
creates a new property in the object and assigns the value of the second index in the deep array to it. - The function returns
a
; whatever is returned by our reducer function becomes the new accumulated value.
-
a
= {} -
a.potatoes
is created and assigned a value of 3;a
= { potatoes: 3 } -
a.tomatoes
is created and assigned a value of 85;a
= { potatoes: 3, tomatoes: 85 } -
a.onions
is created and assigned a value of 27;a
= { potatoes: 3, tomatoes: 85, onions: 27 }
Conclusion
reduce()
is a powerful method that can be used to transform data in an array in many ways. It can be a bit confusing at the beginning. But for me, the trick was to understand that the result of each run of the callback function will be stored in the first argument it takes, this little a
or accumulator
.
Top comments (11)
That's why it's important use well named variables, imagine that your first approach with reduce was this way:
arr.reduce((accumulator, currentValue) => accumulator + currentValue)
;Much better, don't you think so? It's almost self explanatory...
I'm pretty sure I would still have found a way to be confused by it, hahaha
But I do agree that clear naming goes a long way to help understand code.
This is still confusing to someone who has never worked with
reduce()
. But then makes explaining it a bit more easy.This is a great post - really well written and clear; it removes all the confusion surrounding
reduce
. Thanks Pixie! :]Nice explanation, well done 👏
This was awesome, thanks for the article.
"I understand that a and b are supposed to be elements in the array, but how on earth does JavaScript know which one is which?"
I don't understand any of these questions you were asking when first analyzing reduce. First a and b were not elements in an array, but rather parameters, that is how they are figured out which are which. The person asking those questions, don't understand the difference between functions and arrays.
Well,
b
is an element of the array in the sense that it represents the element currently being processed in the array. Even MDN speaks of it that way (and evena
would be an element in the array for the first invocation of the callback function in that particular case.)At any rate, I think the root of our misunderstanding is that you seem to be taking my words as talking about their syntactic function (so to speak), while I'm talking about the value they represent and how
reduce()
deals with them.Thanks, sometimes I forget how to use the function and topic like this is so helpful
Hi, where would the semicolons be placed in example 2?
holy s**t!!! it's so clear now, thank you!!