And a practical guide to the reduce() function
There are three primary methods to iterate over an array in JavaScript: forEach
, map
, and reduce
. Each of these functions has its own use case, and it’s important to understand the differences between them.
forEachSection titled: forEach
The forEach
method is the most basic of the three. It performs a simple iteration over an array, and doesn’t return anything. As it’s name implies, it is mostly equivalent to a for…of loop in JavaScript.
Use forEach
when:
- You just want to loop over the array
- Your callback function doesn’t return anything
- When you want to mutate (i.e. change something inside of) objects in the array
- e.g.
array.forEach((item) => item.foo = 'bar')
- e.g.
DO NOT USE forEach
WHEN:
- You want to
await
one or more promisesforEach
is synchronous, so it will not wait for the async function to finish before moving on to the next iteration (making the callback functionasync
will not help)- You have to decide whether you want to wait for the promises in sequence (one at a time), or in parallel (all at the same time).
- If you want to wait for the promises in sequence, use a for…of loop.
- If you want to wait for the promises in parallel, use
map()
to generate an array of promises, and then pass that to Promise.all()
mapSection titled: map
The map
method transforms each element in the array. Its only argument is a callback function that takes the original array item and outputs a different array item.
map
returns a new array with the same length as the original array, but with each element transformed.
Unlike forEach
, the map
callback function can be async
. Doing so will make map
return an array of Promises, which you can then process in parallel (all at the same time) by passing the array returned from map to await Promise.all()
. If you want to process the Promises in sequence (one at a time), you can await them inside of a for...of
loop instead, and manually push the results into a new array.
Use map
when:
- You want to take each item in the array and transform it in some way
- You want to process a batch of async functions in parallel (all at the same time)
DO NOT USE map
WHEN:
- You just want to iterate over the array. A simple iteration should be performed by
forEach
(or a for loop), notmap
. - You want to process a batch of async functions in sequence (one at a time)
reduceSection titled: reduce
The reduce
method takes an array and reduces it to a single value. That single value is usually either an object or a number. Reduce tends to confuse people more than the other two, but 99% of the time reduce
is used for one of two tasks.
Use reduce
when:
- You want to sum up some numeric value contained in each item in the array
- This is happening when
0
is passed as the final argument to reduce
- This is happening when
- You want to transform the array into an object; indexing each item by some property
- This is happening when
{}
is passed as the final argument to reduce
- This is happening when
The signature of reduce
can also be intimidating because it usually has a big inline function, but without the inline function it just looks like this:
The callback
function is called once for each item in the array. It takes two arguments: accumulator
and currentValue
.
-
accumulator
: Remember before when we said thatreduce()
reduces an array to a “single value”? That single value is theaccumulator
. Every iteration of the callback function has to return something. Whatever you return from the callback will be passed in as theaccumulator
for the next iteration of the callback function. That’s how it “accumulates”. -
currentValue
is just the current item in the array. It’s common to change the name of this argument to something more descriptive, specific to your situation.
Example of (1): summing up a numeric valueSection titled: Example of (1): summing up a numeric value
First, here is the classic example of using reduce
to sum up an array of numbers:
But it’s not often you have an array of numbers. It’s usually an array of objects where each object has some numeric value that you want to sum up.
It looks a little more complicated this time because of the inline function, but the only difference is that instead of just a number, we have an object with a numeric value
property.
Example of (2): transforming an array into an objectSection titled: Example of (2): transforming an array into an object
Finding an item in an array is an O(n) operation. If you have an array of 100 items, it could take 100 iterations to find the item you’re looking for. For that reason, if you’re going to be doing a lot of searching, it’s common to transform an array into an object, indexed by your search value, so that you can find the value immediately (in constant, O(1), time), without going through the whole array.
Let’s transform this array into this object, so that we can search for each item by it’s id
.
And that can be done with reduce
like this: