In JavaScript, you can fold an array to a single value with the reduce() method.
The reduce() method works such that it:
- Takes an initial value.
- Sets the result as the initial value to start with.
- Calls a function on the result and the first element.
- Updates the result to the return value of this function call.
- Calls a function on the updated result and the second element.
- Repeats until there are no values left in the array.
- Returns the result.
The reduce() method accumulates the array of elements into a single cumulative value.
For example, let’s calculate a sum of an array of numbers:
const numbers = [1, 2, 3, 4] const sum = numbers.reduce((x, y) => x + y) console.log(sum)
Output:
10
This is a great demonstrative example of how to reduce an array to a single value.
However, there is so much more to learn about reducing in JavaScript.
In this guide, you learn
- How the reduce() method works.
- Different ways to call the reduce() method.
- A bunch of practical use cases.
- Relationship with map() and filter().
And much more.
You are also going to see a bunch of great illustrative examples to back up the theory.
The Array.reduce() Method in JavaScript
In JavaScript, you can loop through an array with the reduce() method to produce a single value.
This is a shorthand approach for creating a complex for or while loop to get the job done.
How Does reduce() Work
JavaScript’s reduce() method implements what is known as folding in maths.
To put it simply, folding means you reduce a list of numbers into a single value.
For instance, calculating the sum of a list of numbers is a great real-life example of folding.
When you calculate the sum of a list of numbers, you:
- Take the first number and add the second number to it.
- Keep the result in your mind.
- Take the second number and add it to the result.
- Keep the result in your mind.
- Take the third number and add it to the result.
You repeat this process until you have summed up all the numbers in the list.
This is exactly how the reduce() method works in JavaScript.
The reduction generally follows this procedure:
- Call a function on the first two elements of an array to get a partial result.
- Call the function on this partial result and the third element of the array to get a new partial result.
- Repeat this process until there are no values left in the array.
- Return the result.
Now you understand the working principle of the reduce() method.
To learn how to use the reduce() method, let’s start by learning its syntax.
Syntax
The most common way to use the reduce() method is by following this syntax:
reduce(function(previousValue, currentValue) { /* actions */}, initialValue)
Where:
- function is a callback function, commonly known as a reducer. This function has to return a value.
- previousValue the previous result returned by the reducer function.
- currentValue the value of the current array element.
- initialValue is the optional starting value for the end result. If unspecified, the first element in the array is used by default.
To make more sense of this, let’s see an example.
Example: How to Use the reduce() Method
Perhaps the easiest example to demonstrate reduce() is by summing up numbers in an array of numbers.
const numbers = [1, 2, 3, 4] const sum = numbers.reduce(function(x, y) { return x + y }, 0) console.log(sum)
Output:
10
Here the reduce() method takes a function that sums up two arguments x and y, where x represents the result so far and y is the current element.
The second argument in the reduce() function is 0. This is the initial value we want the sum to start from.
Under the hood, here are the calculations made by this particular reduce() method call:
- 0 + 1 = 1
- 1 + 2 = 3
- 3 + 3 = 6
- 6 + 4 = 10
Here is a great illustration of the process
![reduce accumulating the sum of an array](https://www.logilax.com/wp-content/uploads/2023/08/javascript-reduce-illustration.png)
By the way, the function passed into the reduce() method call is an example of an inline callback function.
In total, there are 3 different ways to provide the function as an argument to the reduce() method:
- Callback function
- Inline callback function
- Arrow function
These are important to understand because, with each approach, the code looks a bit different although it produces the exact same result.
Furthermore, if you are using other array methods like map() or filter(), you are going to benefit from understanding these types of functions.
The 3 Types of Reducer Functions
As you now know, the reduce() method takes a function argument.
This function can be a callback function, an inline callback function, or an arrow function.
By the way, these 3 types of functions are not only related to the reduce() method. Instead, these types of functions can be used anywhere where you pass a function as an argument to another function.
These types of argument functions look different but behave the same way.
You should pick one based on the context.
- A callback is useful when you use the functionality multiple times.
- An inline callback is useful if you only need the reducer functionality once.
- An arrow function is a more concise way to write an inline callback function. Arrows functions were introduced in ES6.
Let’s take a look at each type of reducer function mentioned above.
1. Callback Function
In JavaScript, a callback function is a function passed as an argument into another function (or method).
To use a callback function with the reduce() method, you need to:
- Have an array of values.
- Specify a separate reducer function.
- Pass the reducer as an argument to the reduce() method call.
For instance, let’s calculate the sum of an array of numbers this way:
const numbers = [1, 2, 3, 4] function add(x, y) { return x + y } const sum = numbers.reduce(add, 0) console.log(sum)
Output:
10
As you can see, here we have a separate function called add which we pass into the reduce() method.
The add argument is an example of a callback function.
This argument add is a reference to the actual implementation of the add() function.
In this case, you do not need to provide any arguments because the reduce() method does it on your behalf.
Next, let’s take a look at what is an inline callback in JavaScript. This is the one you already saw in one of the previous chapters.
2. Inline Callback Function
An inline callback function is a callback that is implemented directly into the function call.
The word inline literally means “in-line”, that is, defined on the same line where it is called.
An inline callback is useful because you do not need to specify a separate function for the reduce() method.
Instead, you can create a one-time function directly into the reduce() method call.
This is good practice if you only need the functionality once. It would not make any sense to leave unused functions hanging in the codebase.
Let’s see an example of using the reduce() method with an inline callback function:
const numbers = [1, 2, 3, 4] const sum = numbers.reduce(function(x, y) { return x + y }, 0) console.log(sum)
Output:
10
Here the functionality for adding up two numbers is implemented directly into the reduce() method call.
Although this makes the code nice and short, you can do things even better by using arrow functions.
3. Arrow Function
In JavaScript, an arrow function is a shorthand for a function expression.
Notice that you cannot always use an arrow function.
An arrow function can be used with these syntaxes:
param => expression (param1, param2) => expression param => { multiple_expressions }
Compare these to the regular function expression:
function name(param1, param2) { expressions }
These can make reduce() method calls way more readable and concise.
For instance, let’s repeat summing up an array of numbers once more using an arrow function:
const numbers = [1, 2, 3, 4] const sum = numbers.reduce((x, y) => x + y) console.log(sum)
Output:
10
Fabulous!
This piece of code looks quite professional, doesn’t it?
Next, let’s discuss closely related built-in array functions map() and filter().
Relation to map() and filter() Methods
Some of you may have noticed the reduce() method has similarities to array methods like map() or filter().
This is not a coincidence.
You can actually use the reduce() method for similar tasks as the map() and filter() methods.
Use reduce() like map()
You can use the reduce() method to complete a task you would do with the map() method.
In short, the map() method loops through an array and transforms it into another array by calling a function on each element in the array.
To read a full guide on the map() method, check this article out.
Anyway, here is an example of using the map() method:
const numbers = [1, 2, 3, 4] const squaredNums = numbers.map(n => n * n) console.log(squaredNums)
Output:
[ 1, 4, 9, 16 ]
But this is something you could do with the reduce() method as well.
For example, let’s square a list of numbers:
const numbers = [1, 2, 3, 4] const squaredNums = numbers.reduce((squares, x) => { squares.push(x * x) return squares }, []) console.log(squaredNums)
Output:
[ 1, 4, 9, 16 ]
In this case, it would actually make more sense to use the map() method because it is way simpler.
Let’s take a look at another commonly used array method, filter(), and its relationship to the reduce() method.
Use reduce() like filter()
In JavaScript, you can use the filter() method to filter out values of an array.
For example, let’s filter out all the odd values from an array of numbers:
const numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] const evenNums = numbers.filter(x => x % 2 == 0) console.log(evenNums)
Output:
[ 2, 4, 6, 8, 10 ]
What you might not think about is you can achieve the same result using the reduce() method.
For example:
const numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] const evenNums = numbers.reduce((evens, x) => { if (x % 2 == 0) evens.push(x) return evens }, []) console.log(evenNums)
Output:
[ 2, 4, 6, 8, 10 ]
But as you can see, this is rather verbose compared to the filter() approach.
Thus, it is in fact a better idea to use the filter() method in this particular task.
But why was it worth mentioning the map() and the filter() methods?
Let me show you when it can be better to use reduce() instead of map() or filter().
reduce() vs map() / filter()
In the context of mapping/filtering, you should use the functions map() and filter() by default.
However, if you are combining these two, you should consider using the reduce() method.
This is because if you chain a filter() call with a map() call, you are looping through the array twice.
But why loop twice if once is enough?
Let me show you an example.
In this example, we are going to combine the two examples from the previous chapters.
In other words, given an array of numbers, let’s create a new array with only the even numbers squared.
Here is how it looks in the code:
const numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] const evenSquared = numbers.filter(x => x % 2 == 0).map(x => x * x) console.log(evenSquared)
Output:
[ 4, 16, 36, 64, 100 ]
This works perfectly, and the code does not look bad either. The .filter().map() chain is readable and concise.
But you might consider making the code run faster by combining the two loops, filter() and map(), into a single loop by using reduce().
Here is how it looks in the code:
const numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] const evenSquared = numbers.reduce((res, x) => { if(x % 2 == 0) res.push(x * x) return res }, []) console.log(evenSquared)
Output:
[ 4, 16, 36, 64, 100 ]
This only loops through the array once.
However, the code is now rather unreadable and verbose. If there is no clear benefit to doing it this way, you should use an approach that is more readable.
Now that you have extensively used the reduce() method, let’s see a couple of mistakes you should avoid.
Mistakes to Avoid with reduce()
Once you have had enough practice, using the reduce() method becomes easy for you.
Here are two common pitfalls that can cause a lot of headaches when using the reduce() method.
Forgetting the Initial Value
Always remember to set the initial value as the second argument in the reduce() method call.
If you do not, the default initial value is used.
This default value is the array element at the index of 0.
Usually, the default value is actually what you want.
Forgetting to Return
A really common pitfall of using the reduce() method is forgetting to return a value from the reducer function.
The reducer function must return a value. This is because the return value is treated as a partial result.
If there is no return value, the reduce() method does not work.
Notice that if you are using a single-line arrow function as the reducer, you do not need to use the return keyword.
This is because a one-liner arrow function expression implicitly returns the value.
Practical Examples
Here are two practical examples of using the reduce() method in JavaScript.
Group Values: A Tally with reduce()
You can use the reduce() method to group array values by their frequency.
For example, given a list of fruits, let’s create an object that groups the fruits by how many times they occur in the array,
Here is how it looks in the code:
const fruits = [ 'apple', 'orange', 'orange', 'apple', 'cherry', 'grape', 'banana', 'cherry', 'orange' ] const tally = fruits.reduce( (tally, fruit) => { tally[fruit] = (tally[fruit] || 0) + 1 return tally } , {}) console.log(tally)
Output:
{ apple: 2, orange: 3, cherry: 2, grape: 1, banana: 1 }
Flatten an Array
If you are dealing with a 2D array, you can use the reduce() method to flatten it.
This works such that the reduce() method concatenates each sub-array to a single 1D array.
For example:
const nums2D = [ [1, 2, 3], [4, 5, 6], [7, 8, 9] ] const flat = nums2D.reduce((nums1D, row) => nums1D.concat(row), []) console.log(flat)
Output:
[ 1, 2, 3, 4, 5, 6, 7, 8, 9 ]
Advanced Use: 10 Syntaxes to Call reduce()
So far you have seen how to use the reduce() method with this syntax:
reduce(function(previousValue, currentValue) { /* actions */}, initialValue)
However, you can also add some optional arguments to the reducer function.
The full syntax of using the reduce() method is actually:
reduce(function(previousValue, currentValue, currentIndex, array) { /* actions */ }, initialValue)
Where:
- function is a reducer function as discussed earlier.
- previousValue is the partial result.
- currentValue is the current array element.
- currentIndex is the optional index of the current array element.
- array is the optional array on which reduce() is being called.
- initialValue is the optional starting value for the accumulated end result.
Here is an example of a situation in which you can specify the currentIndex.
Let’s say you have an array of names that represent people standing in a line.
Now you want to convert this array of names into an object of position number and the person’s name.
Here is how to do it:
const names = ["Alice", "Bob", "Charlie"] const queue = names.reduce(function(namesData, name, nameIndex) { namesData[nameIndex + 1] = name return namesData }, {}) console.log(queue)
Output:
{ '1': 'Alice', '2': 'Bob', '3': 'Charlie' }
Now each name is associated with a position in the queue.
As you can see, the code is quite clean as you do not need to track the index yourself. Instead, the reducer function takes care of that part.
Usually, you are not going to need these optional parameters.
However, it is good to know they exist.
To put it all together, here are all the possible ways you can call the reduce() method.
These include variations of using callbacks, inline callbacks, arrow functions, and the optional parameters discussed above:
// reduce() with a callback function reduce(callback) reduce(callback, initialValue) // reduce() with inline callback function reduce(function(previousValue, currentValue) { /* actions */ }) reduce(function(previousValue, currentValue, currentIndex) { /* actions */ }) reduce(function(previousValue, currentValue, currentIndex, array) { /* actions */ }) reduce(function(previousValue, currentValue, currentIndex, array) { /* actions */ }, initialValue) // reduce with arrow function reduce((previousValue, currentValue) => { /* actions */ } ) reduce((previousValue, currentValue, currentIndex) => { /* actions */ } ) reduce((previousValue, currentValue, currentIndex, array) => { /* actions */ } ) reduce((previousValue, currentValue, currentIndex, array) => { /* actions */ }, initialValue)
Choosing one depends entirely on what you want to do, what are the limitations, and what you want the code to look like.
Most of the time it is enough to use an arrow function with the previousValue and currentValue.
Conclusion
Today you learned what is the reduce() method in JavaScript and how it works.
To recap, the reduce() method lets you iterate over an array and fold the array to a single value.
For instance, to calculate the sum of an array of numbers, you can use the reduce() method.
The reduce() method works such that it:
- Takes an initial value.
- Sets the result as the initial value to start with.
- Calls a function (reducer function) on the result and the first array element.
- Updates the result to the return value of this call.
- Repeats until there are no values left in the array.
- Returns the result.
This way it accumulates a single result over the entire array.
Although you commonly use reduce() to produce a single value, this is not a restriction. Instead, you can transform an array into another using reduce(), similar to map() or filter().
You can call the reduce() method with
- A callback function
- An inline callback function
- An arrow function