Reputation: 361
I'm sure I'm reading this wrong but MDN says this...
initialValue
Value to use as the first argument to the first call of the callback. If no initial value is supplied, the first element in the array will be used. Calling reduce() on an empty array without an initial value is an error.
then says this...Aren't these saying different things? Thanks!
If initialValue isn't provided, reduce() will execute the callback function starting at index 1, skipping the first index. If initialValue is provided, it will start at index 0.
Upvotes: 7
Views: 2903
Reputation: 24710
In short: [a,b,c].reduce(...)
and [b,c].reduce(..., a)
are sometimes the same thing. A better way to think about it, is that the initialValue
is actually the first intermediate result of your calculation.
To get a better understanding of how reduce works, use the following sum(a,b)
function which logs a text like a+b=c
for each operation it performs.
function sum(a,b) {
const c = a + b;
console.log(`${a} + ${b} => ${c}`)
return c;
}
const arr = [1,2,4,8];
const result = arr.reduce(sum);
console.log(`result=${result}`)
This prints 1+2=3
, 3+4=7
, 7+8=15
and finally result=15
.
const arr = [1];
const result= arr.reduce(sum);
console.log(`result=${result}`)
If there's just one element in the array. Then it won't even call the supplied function at all. It will just return the single element. So in this case it will just print result=1
.
const arr = [];
const result = arr.reduce(sum);
console.log(`result=${result}`)
If there are no elements and no initial value, then it just throws an error: Uncaught TypeError: Reduce of empty array with no initial value
Of course you could just add a check in your code to check the length
of your array.
A pretty solid workaround would be to add an initial value in front of your array.
const arr = [];
const arr2 = [0, ...arr];
const result = arr2.reduce(sum)
The initialValue
parameter offers a better solution. It's tempting to say that initialValue
actually does the same thing. That would be incorrect.
const result = arr.reduce(sum, 0);
In the context of this example however, both lead to the same result. However, actually the initialValue
is not an input value, but it is more like the initial sum.
There is a small difference, which only becomes obvious if you start using reduce
for more complicated transformations.
const inputs = [{value: 1}, {value: 2}, {value:3}];
const total = inputs.reduce((sum, input) => sum + input.value, 0);
The example above again creates a total, but this time it extracts the input from a property value
. We have an input of objects, and a numeric result. In this kind of example an initialValue
is not optional at all. It's mandatory.
Think about what would happen if you didn't have an initialValue
in this example. What would be the value of sum
in the first iteration ?
sum
would actually be {value: 1}
which wouldn't even be a number.
So, in this example it's pretty clear that the initialValue is actually the first intermediate result of your calculation.
Upvotes: 0
Reputation: 95
Unfortunately, I can't just add a comment. Try this, please. This is another explanation of .reduce() function with an example how it works on http://javascript.info. Probably, it will help you to understand this better.
Also, here is the answer to your question about an exception on an empty array without the initial value in another StackOverflow's discussion.
If no initialValue was provided, then previousValue will be equal to the first value in the array and currentValue will be equal to the second. It is a TypeError if the array contains no elements and initialValue is not provided.
Update: probably, this article How JavaScript’s Reduce method works, when to use it, and some of the cool things it can do on freeCodeCamp will be useful.
Upvotes: 3
Reputation: 25383
The wording is a bit confusing, I agree.
Putting the two statements together:
If no initial value is supplied, the first element in the array will be used
If initialValue isn't provided, reduce() will execute the callback function starting at index 1, skipping the first index
These two statements are actually describing two different characteristics of the reduce operation when no initial value is provided:
Does this wording make more sense?:
If no initial value is provided, the first element will be used as the initial value. In this case, the callback function will start at index 1, since index 0 has already been accounted for by using it's value as the default starting value.
Upvotes: 9