-1

so I'm writing this very simple function and I'm trying to return it's result but all I get is NaN error.

Here is my current code:

function m(c) {
    return Math.max(c) - this.length - 1;
}


document.getElementById('app').innerHTML = m([1,4,6,8,43,2]);
<p id="app">

</p>

When I return typeof(a - this.length -1); instead, I get a number as a result.

    function m(c) {
        return typeof(Math.max(c) - this.length - 1);
    }


    document.getElementById('app').innerHTML = m([1,4,6,8,43,2]);
<p id="app">

</p>

So my question is why am I getting NaN error if type of my return statement is a number?

@edit Question number 2. Is there a way for me to change the function so that it displays the result without NaN error?

aMJay
  • 2,215
  • 6
  • 22
  • 34

4 Answers4

3

NaN is of the number type:

console.log(typeof NaN)

The reason you're getting NaN is that you can't just call Math.max on an array. (Try Math.max([1,2])). You'll need to use the spread operator (...).

Also, I assume you meant to use the array's length, since this.length doesn't refer to anything.:

function m(c) {
    return Math.max(...c) - c.length - 1;
}


console.log(m([1,4,6,8,43,2]));

In case you need to support older browsers, replace Math.max(...c) with:

Math.max.apply(null, c)
Cerbrus
  • 70,800
  • 18
  • 132
  • 147
1

You have to use Math.max.apply(null, c). Math.max takes a list of numbers, not an array. That's why you have to use apply to use the array as a argument list.

W4ldi
  • 644
  • 5
  • 11
  • Mdn docs: However, both spread (...) and apply will either fail or return the wrong result if the array has too many elements, because they try to pass the array elements as function parameters. See Using apply and built-in functions for more details. The reduce solution does not have this problem. – Tschallacka Mar 13 '18 at 13:39
1

Because this context is not bound with that array, you can bind it as follow, further, you need to sort the array and get the max value.

function m() {
  var [max] = this.sort((a, b) => b - a);
  return max - this.length - 1;
}

document.getElementById('app').innerHTML = m.bind([1, 4, 6, 8, 43, 2])();
<p id="app"></p>

Or you can Spread the array:

function m(c) {
  return Math.max(...c) - c.length - 1;
}

document.getElementById('app').innerHTML = m([1, 4, 6, 8, 43, 2]);
<p id="app"></p>
Ele
  • 33,468
  • 7
  • 37
  • 75
  • `sort` to get the largest value? `.bind` to work around abuse of `this`? I'd suggest changing the OP's methodology instead of making their hacks "work". – Cerbrus Mar 13 '18 at 13:42
1

this.length is undefined. Replace it with c.length.

Also, math.max doesn't work as you think. If you look at the mdn docs you can see that they recommend a reduce function for arrays.

However, both spread (...) and apply will either fail or return the wrong result if the array has too many elements, because they try to pass the array elements as function parameters. See Using apply and built-in functions for more details. The reduce solution does not have this problem.

So in short.

function m(c) {
   
    var max = c.reduce(function(a, b) {
        return Math.max(a, b);
    });
    return max - c.length - 1;
}


document.getElementById('app').innerHTML = m([1,4,6,8,43,2]);
<p id="app">

</p>
Tschallacka
  • 27,901
  • 14
  • 88
  • 133
  • Can the downvoter explain? The reduce function literally comes from: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/max#Getting_the_maximum_element_of_an_array – Tschallacka Mar 13 '18 at 13:36