Angular icon Get $100 off the 7-Courses Angular Master Bundle!

See the bundle then add to cart and your discount is applied.

days
hours
mins
secs

Exploring Array Reduce in JavaScript

Apr 8, 2020 7 mins read

JavaScript post

Follow along with the Exploring JavaScript Array Methods series!

What is Array Reduce?

Array Reduce is a method that exists on the Array.prototype that was introduced in ECMAScript 5 (ES5) and is supported in all modern browsers.

Array Reduce is the most misunderstood array method and a headache for many developers - if only they’d read this article! Pay close attention to the little details and you’ll succeed with Reduce. The concept of Reduce itself isn’t complex, but the method is just a little different to others that we’re used to.

Think of Array Reduce as: “I want to reduce my array to just a single value”

Array Reduce is commonly used for performing things such as math expressions and equations, for instance calculating the total of a numbers array.

You’ll have likely heard the term “Reducer” before when dealing with things such as Redux or NGRX, a Reducer also is a “Reduce”, returning a single value inside a switch statement.

Exploring JavaScript Array Methods cover

⚡️ FREE eBook: 🔥 ForEach, Map, Filter, Reduce, Some, Every, Find

Todd Motto “This book is straight to the point, syntax exploration, comprehensive guide, real-world examples, tips and tricks - it covers all you need” Todd Motto, author of Exploring JavaScript Array Methods

Here’s the syntax for Array Reduce:

const reducedValue = array.reduce((prev, next, index, array) => {...}, initialValue);

Our reducedValue will contain our reduced value, this is typically a number - however you can compose objects and arrays inside your Reduce, that’s more of an advanced use case though.


Array Reduce syntax deconstructed:

  • Reduce’s first argument is a callback function that exposes these parameters:
    • prev (sometimes called acc for “accumulator” as the value is dynamic, it accumulates the callback’s value and is returned on the next iteration as prev)
    • next (the current element, sometimes called value)
    • index (the element’s index - not commonly used with Find)
    • array (the array we are looping - rarely used)
    • Inside the body of the function we need to return an expression which is then passed to the next iteration as prev - Reduce essentially remembers the value from each iteration and keeps providing you it until your array completes
  • Reduce’s second argument is different to other Array method counterparts we’ve explored so far, instead of thisArg it’s initialValue - allowing us to specifiy an optional initial value for the loop to begin (which gets passed in as prev on the first iteration of the loop, with next being the first array value)
  • IMPORTANT: If no initialValue is set, Reduce will use your first array value as the prev on the first iteration - technically starting the loop on the second array element

See the ECMAScript Array Reduce specification!


In its simplest form, here is how Reduce behaves:

const reduced = [1, 2, 3, 4, 5].reduce((prev, next) => prev + next, 0);
// 15
console.log(reduced);

Simple enough, right? Even if we don’t “get it” right away, we can add up 1, 2, 3, 4, 5 to reach a comfortable 15 - so we’re half way there to understanding Reduce.

When Reduce begins the initialValue (here it’s 0) becomes the first prev value and next is our first array value of 1. If there was no initial value then prev would be 1 (first array value) and next would be 2 (second array value).

These small differences in how Reduce behaves with and without an initialValue likely also contributes to reasons to not fully understanding Reduce.

Developers, like I did, struggled at first with this whole prev and next thing.

So let’s use a really simple demonstration to make sure we get it:

const reduced = [1, 2, 3, 4, 5].reduce((prev, next) => {
  console.log(prev, next);
  return prev + next;
}, 0);

Outputs in the console (each iteration):

0   1   // 0  = initial value,             1 = first array item
1   2   // 1  = previous result (0 + 1)    2 = second array item
3   3   // 3  = previous result (1 + 2)    3 = third array item
6   4   // 6  = previous result (3 + 3)    4 = fourth array item
10  5   // 10 = previous result (6 + 4)    5 = fifth array item

This now explains why we get 15 as a return value (10 + 5) - there is no next value in our array so Reduce will exit and return that final value to our reduced variable.

We’ve only considered numbers at this point, however as Reduce returns any value type, it has very flexible use cases! You could return flattened Arrays, concatenated Strings, new or merged Objects - or whatever else you can come up with!

That’s the basics of Reduce, let’s take a look at a more real-world scenario where we’ve tasked with calculating the sum from Objects - there are multiple approaches I’m also going to show you.

Using Array Reduce

Here’s our data structure that we’ll be using Array Find with:

const items = [
  { id: '🍔', name: 'Super Burger', price: 399 },
  { id: '🍟', name: 'Jumbo Fries', price: 199 },
  { id: '🥤', name: 'Big Slurp', price: 299 }
];

Let’s calculate the total price of all price properties.

Reducing an Array of Numbers

A basic Reduce will sum an array of numbers, so let’s add an Array Map before to return us just each price property - giving us an array of numbers to then Reduce:

const reduced = items
  .map(item => item.price)
  .reduce((prev, next) => prev + next);

// Total: 8.97
console.log(found);

This is a perfectly decent example, and completes the mission we set out to achieve to calculate the total price. However, Reduce offers us a really nice way to work with Objects - which involves the use of the initialValue property…

Reducing an Array of Objects

By supplying an initialValue the prev value becomes 0 to begin the Reduce. This works nicely when adding + to our next.price:

const reduced = items
  .reduce((prev, next) => prev + next.price, 0);

// Total: 8.97
console.log(reduced);

If we didn’t supply 0 we would log Total: NaN because we’d be attempting to add an Object to a number property!

It also saves us another Array Map, keep the code a little cleaner and more efficient.

Give the live demo a try:

Bonus: Reduce-ing without Reduce

Let’s check out a for…in loop example that mimics the behaviour of Array Reduce:

let reduced;
let prev = 0; // "initialValue"

for (let i = 0; i < items.length; i++) {
  const next = items[i];
  prev = prev + next.price;
}

reduced = prev;

First we declare reduced and prev to assign an initialValue of 0 just like Reduce. From there, we’ll loop our items and create a next variable. We then re-assign prev each time and add + our next.price to it.

Once the loop as finished, I’ve assigned prev to reduced to act like Reduce’s final return value.

Summary

You’ve now learned how to use Array Reduce to reduce your array to just a single value.

Array Reduce is a nice and compact way that we can declaratively reduce an array and return any kind of value we’d like. More advanced use cases include composing Objects and Arrays inside your Reduce, but we’ll save them for another time.

If you are serious about your JavaScript skills, your next step is to take a look at my JavaScript courses, they will teach you the full language, the DOM, the advanced stuff and much more!

Exploring JavaScript Array Methods cover

⚡️ FREE eBook: 🔥 ForEach, Map, Filter, Reduce, Some, Every, Find

Todd Motto “This book is straight to the point, syntax exploration, comprehensive guide, real-world examples, tips and tricks - it covers all you need” Todd Motto, author of Exploring JavaScript Array Methods

Further tips and tricks:

  • Remember to specify an initialValue when dealing with an Array of Objects
  • Reducing Arrays of Numbers is nice and clean, try not to overcomplicate your Reduce functions - this is a common pattern I’ve seen
  • Don’t forget to return inside your callback, or your values will be undefined and evaluate to false - avoid undetected bugs!
  • You can access the array you’re looping in the third argument of the callback
  • You can change the this context via a second argument to .reduce(callback, thisArg) so that any references to this inside your callback point to your object
  • You can use arrow functions with Every but remember that this will be incorrect if you also supply a thisArg due to arrow functions not having a this context
  • Using Find will skip empty array slots as if it were a falsy value
  • You shouldn’t need to in this day and age of evergreen browsers, but use a polyfill for older browsers if necessary

Thanks for reading, happy Reducing!

Go to the next article in Exploring JavaScript Array Methods - Array Some!

You'll also like...