13

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?

0

3 Answers 3

24

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.

Sign up to request clarification or add additional context in comments.

3 Comments

An alternative solution to do it can be: Math.max.apply(null, [1, 2, 3, 4, 5]);
Thx!! It's clear now. I edited my question, but you answer both of my problems with reduce!! It's cool now.
What a bunch of crap, and an unbelievable lack of foresight. How did ECMA not see reduce(max) as a thing that people would write? They need to step up their functional game.
4

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.

Comments

3

Another way to reduce an array to its max value:

var maxVal = [ 1, 2, 3, 4, 5 ].reduce(function(a,b){return a>b?a:b});

(illustrating how reduce works, not that it is the best way to get the max number from an array)

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.