Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

JavaScript reduce can't handle Math functions?

I'm trying an obvious task:

var maxVal = [ 1, 2, 3, 4, 5 ].reduce( Math.max, 0 );

and get:

NaN

as the result. To make it work I have to make an anonymous function this way:

var maxVal = [ 1, 2, 3, 4, 5 ].reduce( function ( a, b ) { 
                                           return Math.max(a, b);
                                       }, 0 );

Could someone tell me why? Both are functions that take two arguments and both return one value. What's the difference?

Another example could be this:

var newList = [[1, 2, 3], [4, 5, 6]].reduce( Array.concat, [] );

The result is:

[1, 2, 3, 0, #1=[1, 2, 3], #2=[4, 5, 6], 4, 5, 6, 1, #1#, #2#]

I can run this example in node.js only under this shape (Array has no concat in node.js v4.12, which I use now):

var newList = [[1, 2, 3], [4, 5, 6]].reduce( [].concat, [] );    

and then get this:

[ {}, {}, 1, 2, 3, 0, [ 1, 2, 3 ], [ 4, 5, 6 ], 4, 5, 6, 1, [ 1, 2, 3 ], [ 4, 5, 6 ] ]

And why is that?

like image 323
trzewiczek Avatar asked Oct 14 '11 12:10

trzewiczek


People also ask

What is reduce () in JavaScript?

The reduce() method executes a user-supplied "reducer" callback function on each element of the array, in order, passing in the return value from the calculation on the preceding element. The final result of running the reducer across all elements of the array is a single value.

When to use reduce in JS?

reduce() method in JavaScript is used to reduce the array to a single value and executes a provided function for each value of the array (from left-to-right) and the return value of the function is stored in an accumulator.

How can you double elements of an array using reduce Please note that you Cannot create additional variables?

You can reduce an array into a new array. For instance, lets reduce an array of amounts into another array where every amount is doubled. To do this we need to set the initial value for our accumulator to an empty array. The initial value is the value of the total parameter when the reduction starts.


2 Answers

The function passed to reduce takes more than 2 arguments:

  • previousValue
  • currentValue
  • index
  • array

Math.max will evaluate all arguments and return the highest:

Math.max(1, 2, 3, 4) === 4;

So in case of passing Math.max to reduce, it will return the highest value from the 4 arguments passed, of which one is an array. Passing an array will make Math.max return NaN because an array is not a number. This is in the specs (15.8.2.11):

Given zero or more arguments, calls ToNumber on each of the arguments and returns the largest of the resulting values.

...

If any value is NaN, the result is NaN

ToNumber will return NaN for an array.

So reducing with Math.max will return NaN in the end.

like image 189
pimvdb Avatar answered Sep 28 '22 13:09

pimvdb


Since Math.max accepts multiple arguments, you can just convert the array to a parameter list via the apply function.

var maxVal = Math.max.apply(Math, [ 1, 2, 3, 4, 5 ]);

See warnings here on limitations of this technique.

like image 30
Raymond Chen Avatar answered Sep 28 '22 13:09

Raymond Chen