Stop Hating On Array.reduce()

ยท

4 min read

There has been some controversy recently about whether or not JavaScript developers should use the Array.reduce() method.

Here's just a few posts that were part of the recent Tweet storm:

Of course, everyone is entitled to their own opinion! But this article is dedicated to why everyone with the opinion that Array.reduce() is bad is wrong ๐Ÿ˜ˆ

Disclaimer: They aren't wrong ๐Ÿ˜… I'm as opinionated as the rest of 'em!

What does it do?

Array.reduce() is an array function in JavaScript that is used to reduce the contents of an array down to a single value using a function called a reducer.

A popular example usage of the function is a reducer that returns the sum of all numbers in an array:

const value = [1,2,3,4].reduce((acc, cur) => { 
    return acc + curr 
}, 0)

// value: 10

The function takes in two arguments:

  1. callback: A callback function, the reducer

  2. initialValue: The initial value the accumulated value builds upon

The callback function takes in 4 optional parameters:

  1. accumulator: The accumulated value

  2. currentValue: The current item in the array you are iterating through

  3. currentIndex: The current index of the array you are iterating through

  4. array: The entire array you are iterating through

A full signature looks like:

const reducer = (accumulator, currentValue, currentIndex, array) = > { 
    return accumulator; 
}

const value = [...].reduce(reducer, 0)

What's the problem?

After digging through the complaints, the recurring theme is that Array.reduce() is too difficult to read and understand.

While reviewing code, scanning through a new codebase or reading documentation, coming across an Array.reduce() requires you to stop and think for a moment about what is actually happening with an array.

These opinions are based around the fact that you can achieve the same result with another Array method such as Array.forEach() or even a simple for loop in a way that is more readable.

While the opinions hit on a good point... they're wrong!

My reasoning

There are a few things that come to mind when I read these comments. I think a lot of the reasoning behind these opinions are perfectly valid! But the frustration is directed at the wrong thing.

My first thought about this matter is that the real frustration isn't about the method signature and complexity at all, but rather about a developer's worst enemy: naming things.

In fact, this in my opinion is so deeply rooted in the controversy that it shows itself in two different ways!

Exhibit A: It shouldn't be named reduce

First, the method itself is named reduce. While this method name makes sense in many situations... the Array.reduce() method is so powerful that it can do far more than reduce an array to a single value.

Consider the following usage of the function:

const smallNumbers = [1,2,3,4,5] 
const largeNumbers = smallNumbers.reduce((newArray, current) => { 
    newArray.push(current ** 2) 
    return newArray 
}, [])

// largeNumbers: [1,4,9,16,25]

In this case, we aren't reducing the initial array at all... we are transforming it! So... is this reason enough to hate Array.reduce()? I think not!

Array.prototype.transform = Array.prototype.reduce;

Boom, fixed.

Obviously, that's a joke. A joke that would fix the problem completely, but still a joke.

Exhibit B: People are lazy when naming parameters

How many times have you seen a loop like the following:

const array = [...] 
let crazyValue = 0; 
for (let i = 0; i < array.length; i++) { 
    for (let j = 0; j < i; j++) { 
        crazyValue = i + j; 
    } 
}

Really?? i and j? Why are these single-character variable names so common that it almost seems normal to look at?

The same (disgusting) problem exists with Array.reduce() usage. You will often see this:

const array = [...]; 
const crazyvalue = array.reduce((acc, curr, i, arr) => { 
    return acc + curr 
}, 0)

acc, curr, i and arr....really guys?? We can do better. Let's fix this confusing problem by being a lot more descriptive with our variable names:

const array = [...]; 
const crazyvalue = array.reduce((total, currentValue, index, originalArray) => { 
    return total + currentValue 
}, 0)

Or better yet:

const array = [...]; 
const initalValue = 0; 
const addValues = (total, currentValue, index, originalArray) => { 
    return total + currentValue; 
}

const crazyvalue = array.reduce(addValues, initialValue)

Now, this may not be the perfect solution but it certainly makes the code a lot easier to read and digest.

What do you think?

So, is Array.reduce() all that bad? Personally, I would say no. If you understand that Array.reduce() is a powerful function that can do more than simply reduce an array to a single value, it is actually pretty easy to follow.

A lot of the issues I see with it are user-errors related to naming conventions.

What do you think? Am I completely off-base here? @ me on Twitter and we can fight about it ๐Ÿคบ

Bonus question:

Array.prototype.transform = Array.prototype.reduce 
const add = (total, current) => total + current 
const intialValue = 0 
const sumOfNumbers = [1,2,3,4,5].transform(add, initialValue)

Yay or nay?

ย