Math.max() without Arguments

In JavaScript, Math.max() without any arguments returns -Infinity. But why?

I posted the following poll on Twitter asking what would be returned if you called JavaScript's Math.max() function without any arguments.

I gave 4 possible answers: undefined, -1, 0, and -Infinity.

I'm just going to go ahead and spoil it for you. The answer is -Infinity (about half of you got it right, yay! 👏). But why?

Let's dive into the possible JavaScript-based implementations of Math.max.

Using reduce to return -Infinity

JavaScript already has one, but if I were to write a max function from scratch, this is how I would do it.

const max = (...values) =>
  values.reduce((max, value) => (value > max ? value : max), -Infinity);

The function accept a single rest parameter called values, which will be an array. reduce is aptly named as it works to translate an array into a single value. We seed the initial maxValue value with -Infinity.

With each iteration through the array, we return value (if it is greater than maxValue) or maxValue. When all values have been compared, we return maxValue to the caller.

So because we seeded maxValue with -Infinity if there are zero items in the array, we return the initial value of maxValue (i.e. -Infinity).

Let's test our code by calling it with some sample data.

assert(max() === -Infinity, 'Should be -Infinity');
assert(max(-1000) === -1000, 'Should be -1000');
assert(max(1, 2, 3) === 3, 'Should be 3');

Yep. They all pass!

This is a short and sweet implementation.

Using reduce to return 0 (or -1)

If we took our code above and replaced the initial value of -Infinity with 0, the code would still work. Or would it?

Let's see this by running our tests again – changing the first one to check for zero instead.

assert(max() === 0, 'Should be 0');
assert(max(-1000) === -1000, 'Should be -1000');
assert(max(1, 2, 3) === 3, 'Should be 3');

As you see, calling max() without any arguments did correctly return 0, but we get an error with the test for -1000.

AssertionError: Should be -1000

Why is max(-1000) failing? What do you think this is returning? It is errantly returning 0 instead of -1000. This is because a value of -1000 is not greater than a maxValue of 0.

People tend to think in terms of positive numbers. Returning 0 would break some valid conditions as we've shown.

Using reduce to return undefined

What if we wanted to return undefined? This isn't a bad idea (my 8-year-old guessed this when I "quizzed" my family) but would add complexity to our solution above.

Let's take a look.

const max = (...values) =>
  values.reduce((max, value) => {
    if (max === undefined) {
      return value;
    return value > max ? value : max;
  }, undefined);

You see, we would explicitly need to check if maxValue was undefined inside of our loop. It works, but conditions add time and code complexity.

In conclusion

We've learned that returning -Infinity or undefined are the only possible valid conditions of the four I presented in my Twitter poll.

However, -Infinity greatly reduces code complexity and IMO, is the best solution.

Follow up from Brendan Eich

It turns out that my guess was right! This is exactly how Math.max is implemented. I received the following tweet from the father of JavaScript, Brendan Eich.