Math.max() without Auguments
Tags: javascript
Published: 2020-03-21 14:59:54

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

{% twitter 1241117895347838989 %}

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 👏). But why?

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

## Using reduce to return -Infinity

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

Here we 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 `max` value with `-Infinity`.

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

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

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

```js
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.

```js
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 `max` 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.

```js
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 `max` 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.

{% twitter 1241428538311340034 %}