Welcome to the Treehouse Community

Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.

Looking to learn something new?

Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.

Start your free trial

JavaScript

Mahmoud Talass
Mahmoud Talass
9,274 Points

reduce() method

Can someone please simplify the reduce() method and its parameters for me. I don't get it at all.

1 Answer

Juan Luna Ramirez
Juan Luna Ramirez
9,038 Points

reduce allows you to do some work for each item in an array. Then, you get something at the end of doing all that work for every item.

Maybe it would help to think about the output or the return value of running the reduce function. Meaning, what do you want to have at the end of running the reduce function? Is it a brand new array, a number, a string, or an object?

Turns out, you can get anything from the reduce function which makes it very flexible but sometimes difficult to grasp, and I guess explain. OK?! O_o

Let's look at the arguments like you suggest. The reduce function takes 2 arguments:

  1. The function that will do the work for each item in the array. This is often referred to as the callback function or reducer function in case you want to research this some more.
  2. The initial value before we even start looping over the array

so we can say the signature is array.reduce(callback, initialValue).

Initial Value

Let talk about the initial value first since I'm trying to explain this in terms of what you want to get at the end of running reduce.

In practice, I almost always (probably always) use the same data type for the initial value as what I want at the end of running the reduce function. What I mean is:

  • If I want to get a number at the end I'll use a number as the initial value. 8 is the initial value

    const numberOutput = [1, 2, 3].reduce(callback, 8)`
    
  • If I want to get an array at the end I'll use an array as the initial value. [] is the initial value

    const arrayOutput = ['hello', 'hi', 'sup'].reduce(callback, [])`
    
  • If I want an object at the end I'll use an array as the initial value. {} is the initial value

    const objectOutput = ['hello', 'hi', 'sup', 'hello'].reduce(callback, {})`
    

And so on!

This however does not guarantee that the end result will be that same data type as I'll try to show at the end. In fact, the initial value is optional and I would encourage you to research what happens if you don't have it. I don't want to complicate it here for you. I would just recommend using an initial value of the same data type as you want at the end, while you get more familiar with reduce.

Callback Function

Now we'll look at the callback function which allows us to do some work for each item in the array. There is some useful information we might need each time we do this work. These are the parameters of the callback function.

  1. The first thing that would be useful to know is how our final output, the thing we want at the end of running the reduce function is looking thus far. This is often referred to as the accumulator
  2. It is also often useful to know the item of the array we are currently on. This is often referred to as the currentValue

There are 2 more argument but you can research this on your own to keep this simple here.

For simplicity, let's just say the signature is callback(accumulator, currentValue)

ACCUMULATOR

This is the thing we want to get at the end of running the reduce function. So how do you control what this is during each item of the array? During the first item of the array, it will be the initial value we passed as the second argument to reduce. After that, it's whatever we return from the previous callback function.

Let's put it all together in an example: I'm going to add all the 1s in the array to the initialValue 10. So at the end of running reduce I expect to get a number which should be 13

// I'm going to declare the callback function separately so you can,
// hopefully, clearly see the callback parameters and the reduce arguments.

// I just named the parameters "accumulator" and "currentValue" as they are often
// called but you can use whatever names makes sense to you.
const callback = (accumulator, currentValue) => {
  // I'm going to add the current 1 which is saved to currentValue
  // to the current accumulator.
  const updatedNumber = accumulator + currentValue

  // IMPORTANT part: now we are going to return the updatedNumber so that
  // THIS updatedNumber will become the next accumulator when we run this function
  // again for the next item in the array. The last time this run is our final
  // output we are looking for.
  return updatedNumber
}


const numberOutput = [1, 1, 1].reduce(callback, 10)

console.log(numberOutput) // 13

Here are the values of each iteration:

iteration current array value ACCUMULATOR
0 1 10
1 1 11
2 1 12

The return value of the last callback function is the final result, the thing you wanted at the end of running the reduce function, the number 13. Phew!!

Another example. At the end I want an array with all the words in upppercase

// I'm going to put the callback function inline now, but it's all the same
const upcased = ['hi', 'hello', 'hola'].reduce((accumulator, currentValue) => {
  // uppercase the current word
  const wordInUpperCase = currentValue.toUpperCase()

  // add the uppercased word to our acccumulator array
  accumulator.push(wordInUpperCase)

  // important: return the array that now has the newly added word so that
  // it becomes the next accumulator array. The last time this is returned
  // becomes the final output we are looking for.
  return accumulator
}, [])

console.log(upcased) // ["HI", "HELLO", "HOLA"]
iteration current array value ACCUMULATOR
0 'hi' []
1 'hello' ["HI"]
2 'hola' ["HI", "HELLO"]

The return value of the last callback function will be ["HI", "HELLO", "HOLA"], our final output we were looking for.

Let me just show you one final and absolutely obsured example, just to point out that the last return value is our final output. I'm going to repeat the adding of number example but this time I'm going to sabotage the whole thing by returning a string at the very last iteration. Again, this is probably not something you would want to do but that you might actually accidentally do, creating a bug!

// I'm going to use the 3rd parameter which is the index so I know we're
// at the last item, where I'm going to sabotage this thing. Again, research
// the additional parameters.
const callback = (accumulator, currentValue, index) => {
  const isLastIteration = index === 2
  const updatedNumber = accumulator + currentValue

  // it's the last iteration, do something crazy!
  if (isLastIteration) {
    return 'nope!!!'
  }

  return updatedNumber
}


const numberOutput = [1, 1, 1].reduce(callback, 10)

console.log(numberOutput) // "nope!!!"

Here are the values of each iteration:

iteration current array value ACCUMULATOR
0 1 10
1 1 11
2 1 12

Everything was working fine till the end because the return value of the last callback function is just "nope!!". This will be the final result we get. lol!


Yeah, this is one is hard but try out some more example and console out the result to see if you can make it work. I would definitely recommend learning this method though, it's very powerful and useful. Search for other explanations. Hope this is somewhat helpful.