Exploring JavaScript’s reduce() Method (Part 1)

Jennifer Ingram
7 min readMar 19, 2019

--

According to current MDN documentation, there are 438 documented JavaScript methods. As JavaScript is the language of the web, I’m determined to master it, or at least, you know, try to keep up.

(I’m the old man in this scenario)

If you’re familiar at all with JavaScript, then you’re probably familiar with JavaScript’s more prominent methods — map(), filter(), the for…in loop, and, if you’ve ever needed to add elements in an array, reduce().

I’ll admit it — reduce() has always been a bit confusing to me. First of all, it takes in a callback function (queue a slightly uncomfortable, almost panicky feeling), and it has some optional arguments which can drastically change what the method returns. But, after playing around with it for a bit in the console, I’m finally understanding some of its nuances.

So, let’s dig in and explore, shall we?

How to Use reduce() to Add Elements in an Array

As I mentioned above, the most common use (I’m guessing) of the reduce() method is to add up elements in an array, so we’ll take a look at that first.

Let’s say I’m a kid with a jar full of coins, and I’m saving up to buy a brand new box of crayons (IMHO, the best thing ever).

coins = [1, 5, 1, 5, 1, 10, 25, 10, 25, 1, 1, 5, 10, 10, 5, 5, 1]

To add all of these coins, we’ll use reduce(). Reduce() takes in a couple of arguments— the dreaded callback function, and an initial value. (The initial value argument is optional, and we’ll take a look at that in just a moment). The callback function doesn’t have to be scary though — it’s actually pretty cool.

Here’s how it looks…

coins.reduce( (accumulator, currentElement) => { }, initialValue )

Notice that the callback function itself takes in two arguments — accumulator and currentElement. It’s important to understand that reduce() is a looping method — it runs once for each element in your array. The accumulator is the value returned each time the reduce() method runs. The currentElement is, you guessed it, the element currently being looked at as the loop runs. If an initialValue is given, then our accumulator will be set to initialValue on our first run through the loop, and our loop will begin with the first element in the array. So, filling out our reduce() method to add our coins will look like this…

coins.reduce( (accumulator, currentElement)=>{return accumulator + currentElement}, 0);

Running this in your console should return 121. So we have 121 cents to apply toward our crayon purchase. Yes!

Here’s a breakdown of what’s happening when the JavaScript engine runs…

On our first iteration, because we assigned an initialValue (0), our accumulator is equal to 0, and our currentElement is the first element in our array, 1.

coins.reduce( (accumulator(0), currentElement(1))=>{return accumulator(0) + currentElement(1)}, 0);

The value returned from our first iteration is 1 (0 + 1), and on our second iteration, the accumulator is reset to 1.

coins.reduce( (accumulator(1), currentElement(5))=>{return accumulator(1) + currentElement(5)}, 0);

The value returned now is 6 (1 + 5), and our accumulator is reset again.

Notice that the accumulator keeps resetting (or accumulating, eh?) through each iteration of the loop. This keeps happening until our loop finishes with the last element in our array, when it spits out the final value, 121.

How Things Change When We Omit an Initial Value

Remember how I said that the initial value argument is optional? Let’s take a look at how things change when we don’t provide an initial value.

coins.reduce( (accumulator, currentElement)=>{return accumulator + currentElement} );

Hmm… running this in the console returns the exact same value — 121. What’s important to remember is that even though we get the same return value by omitting the initial value, that omission completely changes how the reduce() method starts.

From the MDN documentation —

If no initialValue is provided, then accumulator will be equal to the first value in the array, and currentValue(Element) will be equal to the second.

*Just a side note — I prefer to use the variable name currentElement (instead of currentValue) — it just makes the process clearer to me.

For our coins array, this means that on the first iteration through the reduce() method, our accumulator is equal to 1 (the first value in our array), and our currentElement is equal to 5 (the second value in our array).

coins = [1, 5, 1, 5, 1, 10, 25, 10, 25, 1, 1, 5, 10, 10, 5, 5, 1]

coins.reduce( (accumulator(1), currentElement(5))=>{return accumulator(1) + currentElement(5)} );

This may seem pretty simple, but if you don’t remember that the reduce() method has this unique behavior, then you may get some unexpected returns when attempting to use it in the future.

Other Arguments to reduce()’s Callback Function

Besides accumulator and currentElement (which are not optional), reduce() also accepts two other (optional) arguments — currentIndex and array. The currentIndex is, you guessed it, the index of currentElement, and array is simply the array that reduce() is being called on.

Let’s say I have an array of numbers (numbers = [1, 2, 3, 4, 5, 6]) and I want to add every other number in that array, beginning with the first element. I can use the optional currentIndex argument to accomplish this!

In this callback function to reduce(), I have a conditional that is checking the currentIndex — if the currentIndex is even (I’m using the modulo operator to check for a remainder), then I will add that element to the accumulator. If the currentIndex is not even, then I won’t add the current element, but just return the accumulator as it currently stands.

Running this in your console should return 9 — the result of adding 1, 3, and 5 (at indices 0, 2, and 4, respectively).

Setting Out on the Wrong Foot

Now let’s try adding the other numbers (at indices 1, 3, and 5).

Note that the only change I’ve made here is in our conditional (instead of currentIndex % 2 === 0, it’s currentIndex % 2 !== 0).

Running this in the console returns 13. Hey! What gives?! 2 + 4 + 6 = 12, not 13.

So remember that tricksy behavior when an initial value is not provided — here’s what’s happening…

Our reduce() method is saying, ‘Hey! You didn’t provide me with an initial value! I guess this means you want the first element in the array to start off as the value of the accumulator, and the second element to start off as the currentElement? Okay, sure!’ Our first iteration of the reduce() method now looks like this…

numbers = [1, 2, 3, 4, 5, 6]

In this example I’ve plugged in the values from our numbers array according to the rules of the reduce() method. Our accumulator is set to the first element in our array (1), our currentElement is set to the second element in our array (2), and the currentIndex is set to the index of the currentElement (the index of 2 is 1). Our conditional checks to see if our currentIndex (1) is even — it is not — and so our accumulator (1) gets added to our currentElement (2) (1 + 2 = 3), and on the second iteration of our reduce() method, our accumulator is set to 3. This is obviously not what we want, so how do we fix this?

We add an initial value!

Running this in the console now should yield the expected result — 12! Yay!

Other Stuff You Can Do With reduce() Besides Add (Hint… You Can Subtract Too)

Lest I give away the impression that reduce() is really only helpful to add things, let’s explore reduce() just a little bit more.

Going to back to our I’m-a-kid-buying-crayons story, let’s say that I’m shopping around, and I would like to buy a 64-count box for about $4.23, or 423 cents. *I am not however, going to buy this box

Kids — always, always shop around for your purchases to be sure you’re getting a good deal.

Okay, so I’m going to buy the reasonably priced box ($4.23). What I want to know, really, is not how much money I have saved up, but how much more I need to buy my crayons. I can use reduce() to do this…

Here I set the initial value to 423, and with each iteration I subtract my coins. Pretty sneaky!

This returns 302 cents, or $3.02. Perfect! Time to go raid the couch cushions one more time…

I knew my couch was eating things.

In Conclusion…

There really is so much more that you can do with the reduce() method (hint… it goes waaay beyond adding and subtracting), but the drama of our crayon story was pretty mentally and emotionally exhausting, so I’ll address those in my next blog — Exploring JavaScript’s reduce() Method (Part 2). See you soon…

--

--

Jennifer Ingram

Software Developer. Art and art history lover. Museum explorer. Total cat lady.