In JavaScript, why does `isNaN(" ")`

evaluate to `false`

, but `isNaN(" x")`

evaluate to `true`

?

I’m performing numerical operations on a text input field, and I’m checking if the field is `null`

, `""`

, or `NaN`

. When someone types a handful of spaces into the field, my validation fails on all three, and I’m confused as to why it gets past the `isNaN`

check.

JavaScript interprets an empty string as a 0, which then fails the isNAN test. You can use parseInt on the string first which won't convert the empty string to 0. The result should then fail isNAN.

You may find this surprising or maybe not, but here is some test code to show you the wackyness of the JavaScript engine.

```
document.write(isNaN("")) // false
document.write(isNaN(" ")) // false
document.write(isNaN(0)) // false
document.write(isNaN(null)) // false
document.write(isNaN(false)) // false
document.write("" == false) // true
document.write("" == 0) // true
document.write(" " == 0) // true
document.write(" " == false) // true
document.write(0 == false) // true
document.write(" " == "") // false
```

so this means that

```
" " == 0 == false
```

and

```
"" == 0 == false
```

but

```
"" != " "
```

Have fun :)

Try using:

```
alert(isNaN(parseInt(" ")));
```

Or

```
alert(isNaN(parseFloat(" ")));
```

To understand it better, please open Ecma-Script spec pdf on page 43 "ToNumber Applied to the String Type"

if a string has a numerical syntax, which can contain any number of white-space characters, it can be converted to Number type. Empty string evaluates to 0. Also the string 'Infinity' should give

```
isNaN('Infinity'); // false
```

Antonio Haley's highly upvoted and accepted answer here makes a wrong assumption that this process goes through JavaScript's `parseInt`

function:

You can use parseInt on the string ... The result should then fail isNAN.

We can easily disprove this statement with the string `"123abc"`

:

```
parseInt("123abc") // 123 (a number...
isNaN("123abc") // true ...which is not a number)
```

With this, we can see that JavaScript's `parseInt`

function returns `"123abc"`

as the number `123`

, yet its `isNaN`

function tells us that `"123abc"`

*isn't* a number.

ECMAScript-262 defines how the `isNaN`

check works in section 18.2.3.

## 18.2.3

`isNaN`

(Number)The

`isNaN`

function is the`%isNaN%`

intrinsic object. When the`isNaN`

function is called with one argument number, the following steps are taken:

- Let
`num`

be ?`ToNumber(number)`

.- If
`num`

is`NaN`

, return`true`

.- Otherwise, return
`false`

.

The `ToNumber`

function it references is also defined in ECMAScript-262's section 7.1.3. In here, we get told how JavaScript handles Strings which are passed in to this function.

The first example given in the question is a string containing nothing but white space characters. This section states that:

A

`StringNumericLiteral`

that is empty or contains only white space is converted to`+0`

.

The `" "`

example string is therefore converted to `+0`

, which is a number.

The same section also states:

If the grammar cannot interpret the

`String`

as an expansion of`StringNumericLiteral`

, then the result of`ToNumber`

is`NaN`

.

Without quoting all of the checks contained within that section, the `" x"`

example given in the question falls into the above condition as it cannot be interpreted as a `StringNumericLiteral`

. `" x"`

is therefore converted to `NaN`

.

I'm not sure *why*, but to get around the problem you could always trim whitespace before checking. You probably want to do that anyway.

I suggest you to use the following function if you really want a proper check if it is an integer:

```
function isInteger(s)
{
return Math.ceil(s) == Math.floor(s);
}
```

That `isNaN(" ")`

is false is part of the confusing behavior of the `isNaN`

global function due to its coercion of non-numbers to a numeric type.

*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.

The `isNaN`

function expects a Number as its argument, so arguments of any other type (in your case a string) will be converted to Number *before* the actual function logic is performed. (Be aware that `NaN`

is also a value of type Number!)

Btw. this is common for *all* built-in functions - if they expect an argument of a certain type, the actual argument will be converted using the standard conversion functions. There are standard conversions between all the basic types (bool, string, number, object, date, null, undefined.)

The standard conversion for `String`

to `Number`

can be invoked explicit with `Number()`

. So we can see that:

`Number(" ")`

evaluates to`0`

`Number(" x")`

evaluates to`NaN`

Given this, the result of the `isNaN`

function is completely logical!

The real question is why the standard String-to-Number conversion works like it does. The string-to-number conversion is really intended to convert numeric strings like "123" or "17.5e4" to the equivalent numbers. The conversion first skips initial whitespace (so " 123" is valid) and then tries to parse the rests as a number. If it is not parseable as a number ("x" isn't) then the result is NaN. But there is the explicit special rule that a string which is empty or only whitespace is converted to 0. So this explains the conversion.

Reference: http://www.ecma-international.org/ecma-262/5.1/#sec-9.3.1

I wrote this quick little function to help solve this problem.

```
function isNumber(val) {
return (val != undefined && val != null && val.toString().length > 0 && val.toString().match(/[^0-9\.\-]/g) == null);
};
```

It simply checks for any characters that aren't numeric (0-9), that aren't '-' or '.', and that aren't undefined, null or empty and returns true if there's no matches. :)

As other explained the `isNaN`

function will coerce the empty string into a number before validating it, thus changing an empty string into 0 (which is a valid number).
However, I found that the `parseInt`

function will return `NaN`

when trying to parse an empty string or a string with only spaces. As such the following combination seems to be working well:

`if ( isNaN(string) || isNaN(parseInt(string)) ) console.log('Not a number!');`

This check will work for positive numbers, negative numbers and numbers with a decimal point, so I believe it covers all common numerical cases.

This function seemed to work in my tests

```
function isNumber(s) {
if (s === "" || s === null) {
return false;
} else {
var number = parseInt(s);
if (number == 'NaN') {
return false;
} else {
return true;
}
}
}
```

The ** JavaScript** built-in

`"", " ", " 000"`

, cannot be NaN. Meaning that the *argument* supplied will first undergo a *conversion* as in:

```
function isNaNDemo(arg){
var x = new Number(arg).valueOf();
return x != x;
}
```

**Explanation:**

In the top line of the function body, we are (first) trying to successfully convert the argument into a number object. And (second), using the dot operator we are - for our own convenience - immediately stripping off, *the primitive value* of the created object.

In the second line, we are taking the value obtained in the previous step, and the advantage of the fact that ** NaN** is not equal to anything in the universe, not even to itself, e.g.:

`NaN == NaN >> false`

to finally compare it (for inequality) with itself.This way the function return will yield ** true** only when, and only if, the supplied argument-return, is a failed attempt of conversion to a number object, i.e., a not-a-number number; e.g., NaN.

*isNaNstatic( )*

However, for a Static Type Operator - if needed and when needed - we can write a far simpler function such as:

```
function isNaNstatic(x){
return x != x;
}
```

And avoid the DTC altogether so that if the argument is not explicitly a NaN number, it will return false. Wherefore, testing against the following:

`isNaNStatic(" x"); // will return false`

because it's still a string.

However:
`isNaNStatic(1/"x"); // will of course return true.`

as will for instance `isNaNStatic(NaN); >> true`

.

But contrary to `isNaN`

, the `isNaNStatic("NaN"); >> false`

because it (the argument) is an ordinary string.

p.s.: The static version of isNaN can be very useful in modern coding scenarios. And it may very well be one of the main reasons I took my time for posting this.

Regards.

`isNAN(<argument>)`

is a function to tell whether given argument is illegal number.
`isNaN`

typecasts the arguments into Number type. If you want to check if argument is Numeric or not? Please use `$.isNumeric()`

function in jQuery.

That is, isNaN(foo) is equivalent to isNaN(Number(foo)) It accepts any strings having all numerals as numbers for obvious reasons. For ex.

```
isNaN(123) //false
isNaN(-1.23) //false
isNaN(5-2) //false
isNaN(0) //false
isNaN('123') //false
isNaN('Hello') //true
isNaN('2005/12/12') //true
isNaN('') //false
isNaN(true) //false
isNaN(undefined) //true
isNaN('NaN') //true
isNaN(NaN) //true
isNaN(0 / 0) //true
```

I use this

```
function isNotANumeric(val) {
if(val.trim && val.trim() == "") {
return true;
} else {
return isNaN(parseFloat(val * 1));
}
}
alert(isNotANumeric("100")); // false
alert(isNotANumeric("1a")); // true
alert(isNotANumeric("")); // true
alert(isNotANumeric(" ")); // true
```

`NaN`

!== "not a number"

`NaN`

is a value of Number Type

this is a definition of isNaN() in ECMAScript

```
1. Let num be ToNumber(number).
2. ReturnIfAbrupt(num).
3. If num is NaN, return true.
4. Otherwise, return false.
```

Try to convert any value to Number.

```
Number(" ") // 0
Number("x") // NaN
Number(null) // 0
```

If you want to determine if the value is `NaN`

, you should try to convert it to a Number value firstly.

When checking if certain string value with whitespace or `" "`

is `isNaN`

maybe try to perform string validation, example :

```
// value = "123 "
if (value.match(/\s/) || isNaN(value)) {
// do something
}
```

From `MDN`

reason for the issue you are facing

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.

You may want to check the following comprehensive answer which covers the NaN comparison for equality as well.

I think it's because of Javascript's typing: `' '`

is converted to zero, whereas `'x'`

isn't:

```
alert(' ' * 1); // 0
alert('x' * 1); // NaN
```

If you would like to implement an accurate isNumber function, here is one way to do it from *Javascript: The Good Parts* by Douglas Crockford [page 105]

```
var isNumber = function isNumber(value) {
return typeof value === 'number' &&
isFinite(value);
}
```

The function `isNaN("")`

performs a **String to Number type coercion**

ECMAScript 3-5 defines the following return values for the typeof operator:

- undefined
- object (null, objects, arrays)
- boolean
- number
- string
- function

Better to wrap our test in a function body:

```
function isNumber (s) {
return typeof s == 'number'? true
: typeof s == 'string'? (s.trim() === ''? false : !isNaN(s))
: (typeof s).match(/object|function/)? false
: !isNaN(s)
}
```

This function is not intented to test variable *type*, instead it tests the *coerced value*. For instance, booleans and strings are coerced to numbers, so perhaps you may want to call this function as `isNumberCoerced()`

if there's no need to test for *types* other than *string* and *number*, then the following snippet might be used as part of some condition:

```
if (!isNaN(s) && s.toString().trim()!='') // 's' can be boolean, number or string
alert("s is a number")
```

What about

```
function isNumberRegex(value) {
var pattern = /^[-+]?\d*\.?\d*$/i;
var match = value.match(pattern);
return value.length > 0 && match != null;
}
```

©2020 All rights reserved.