Mateja Petrovic
Mateja Petrovic

Reputation: 4317

Javascript Array.reduce with Math.max

Why does the second example return NaN, whereas the first one works?

const numbers = [ 1, 2, 3 ]

console.log('passing arrow funciton', numbers.reduce((l, r) => Math.max(l, r)) ) // 3

console.log('passing bound function', numbers.reduce(Math.max.bind(Math)) ) // NaN

To give you some context the reduce function requires a Callback param. Furthermore, the callback requires two params, the Accumulation and Current element ( you can also call them left and right etc. ). There are more parameters but they are optional.

I've tried to mock the reduce function and the example works like a charm

const numbers = [1, 2, 3]

const reduce = (array, func) => {

  let largest = 0

  array.forEach
  (
    (number, i, a) =>
      a[i + 1]
      ? largest = func(number, a[i + 1])
      : console.log('done')
  )

  return largest

}

console.log( 'mock reduce', reduce(numbers, Math.max.bind(Math)) ) // 3

enter image description here

Upvotes: 3

Views: 548

Answers (1)

Pointy
Pointy

Reputation: 413702

The callback to .reduce() is passed 4 parameters: the accumulator, the current element, the index, and the overall array. The NaN is coming from the attempt to convert the array itself to a number.

On the first call to the callback, therefore, .max() will be passed 1, 2, 1, [1, 2, 3]. That'll return NaN, and it'll then be NaN all the way. Besides the problem of the NaN from the array, the index value could also throw off the accuracy of the result if you had a long array with lots of small or negative numbers.

Note that what I'm describing here is the argument list that .reduce() passes to the callback function provided, not the arguments to .reduce() itself. The .reduce() function always passes all four parameters to the callback, but the nature of JavaScript is that functions can ignore excess parameters. That's exactly what your first example does.

Upvotes: 6

Related Questions