1

I've found that an empty array or an arwith exactly one Number is a Number.

This topic is not really an explanation for this special case I think: Why does isNaN(" ") equal false

document.write( isNaN([1,2,3]) ); // true
document.write( isNaN([1,2,'abc']) ); // true
document.write( isNaN(['abc']) ); // true

// maybe explained through the above link
document.write( isNaN([]) ); // false

// but...
document.write( isNaN([1]) ); // false
document.write( isNaN([-3]) ); // false
document.write( isNaN([1234567]) ); // false
document.write( isNaN([-1.234]) ); // false
document.write( isNaN([[123]]) ); // false
document.write( isNaN(['1']) ); // false

Who can tell me why it makes sense?

Community
  • 1
  • 1
algorhythm
  • 8,530
  • 3
  • 35
  • 47

2 Answers2

3

isNaN coerces its value to a number. (See MDN)

Because the string representation of an array is all of its items concatenated with a comma. And the numerical representation of that is NaN because of the comma.

But if there's only one item, hence no comma, it's able to be converted to a number.

Scimonster
  • 32,893
  • 9
  • 77
  • 89
  • Yeah, but how does that make sense? – algorhythm Nov 24 '14 at 13:13
  • @algorhythm check the [MDN: isNaN()](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/isNaN) and the difference between the old global `isNaN()` and the `Number.isNaN()` – t.niese Nov 24 '14 at 13:15
  • 2
    @algorhythm `isNaN`: "[Returns `true` if the argument coerces to `NaN`, and otherwise returns `false`.](http://www.ecma-international.org/ecma-262/5.1/#sec-15.1.2.4)" -- Here "coerces" means using the [`ToNumber`](http://www.ecma-international.org/ecma-262/5.1/#sec-9.3) abstract operation on the argument, which stringifies objects (like Arrays) and then number-ifies strings (like `"1234567"`, which is the stringified form of `[1234567]`). If the stringified form of the object has a comma (like `"1,2,3"`), then the string can't be sensibly converted to a number, so it's coerced to `NaN`. – apsillers Nov 24 '14 at 13:17
  • 2
    Note that there is special case where if a string contains only whitespace, then *ToNumber* returns `0`, so `isNaN('\n')` returns false, while `isNaN('foo')` (or any other non–numeric string literal) returns true. – RobG Nov 24 '14 at 13:24
0

You're using the isNaN global function which has some confusing behavior due to its coercion of non-numbers to a numeric type which can then result in the NaN value. This is what is happening in your case as the string representation of an array containing a single number element will successfully parse to the number value of the single number element.

From MDN:

Since the very earliest versions of the isNaN function specification, its behavior for non-numeric arguments has been confusing. When the argument to the isNaN function is not of type Number, the value is first coerced to a Number. The resulting value is then tested to determine whether it is NaN. Thus for non-numbers that when coerced to numeric type result in a valid non-NaN numeric value (notably the empty string and boolean primitives, which when coerced give numeric values zero or one), the "false" returned value may be unexpected; the empty string, for example, is surely "not a number."

Note also that with ECMAScript 6, there is also now the Number.isNaN method, which according to MDN:

In comparison to the global isNaN() function, Number.isNaN() doesn't suffer the problem of forcefully converting the parameter to a number. This means it is now safe to pass values that would normally convert to NaN, but aren't actually the same value as NaN. This also means that only values of the type number, that are also NaN, return true.

Unfortunately:

Even the ECMAScript 6 Number.isNaN method has its own issues, as outlined in the blog post - Fixing the ugly JavaScript and ES6 NaN problem.

lucono
  • 21
  • 1