在JavaScript中如何检查一个数字是否为NaN?

544

我只在Firefox的JavaScript控制台中尝试过,但以下语句都没有返回true:

parseFloat('geoff') == NaN;

parseFloat('geoff') == Number.NaN;

6
如果您的实际目标是检查数字, 这篇文章值得一读:https://dev59.com/3nVD5IYBdhLWcg3wU56H - Paul
3
http://designpepper.com/blog/drips/the-problem-with-testing-for-nan-in-javascript.html - Foreever
1
@Gothdo:好的,但是我确实问过如何检查一个数字是否为NaN,而不是任何值。 - Paul D. Waite
3
@PaulD.Waite 是的,但很多人在谷歌搜索"如何在JavaScript中检查变量是否为NaN"时会来到这里。 - Michał Perłakowski
在ES6(又名ECMAScript 2015)中,使用Number.isNaN,查看此答案MDN - undefined
显示剩余4条评论
33个回答

726

10
需要使用parseFloat吗? - rahul
27
如果你希望将空字符串解释为“NaN”,那么是的。(我不是说你总是这样做。) - Paul D. Waite
1
如果我是你,我会将其分配给一个变量,并使用条件变量!== =变量。正如规范中所述https://tc39.github.io/ecma262/#sec-isnan-number - ALLSYED
7
isNaN(parseFloat("geoff")) // true 的意思是判断字符串 "geoff" 能否被转换成数字,由于无法转换,返回值是 true。isNaN(parseFloat("10geo")) // false 的意思是判断字符串 "10geo" 能否被转换成数字,由于可以转换成数字 10,返回值是 false。这个函数对于验证用户输入是否为数字非常有用。 - Prashanth
@PaulD.Waite,为什么应该使用parseFloat而不是parseInt - norbekoff
显示剩余2条评论

178

我在Effective JavaScript这本书中发现了一个非常简单的技巧:

由于NaN是JavaScript中唯一被视为与自身不相等的值,因此您可以通过将其与自身进行比较来测试一个值是否为NaN:

var a = NaN;
a !== a; // true 

var b = "foo";
b !== b; // false 

var c = undefined; 
c !== c; // false

var d = {};
d !== d; // false

var e = { valueOf: "foo" }; 
e !== e; // false

在@allsyed的评论之前没有意识到,但这在ECMA规范中有说明:https://tc39.es/ecma262/multipage/global-object.html#sec-isnan-number


46
高效但很反直觉。我不想维护这种类型的代码。 - Sergey Orshanskiy
47
反直觉的不是代码,而是 NaN。 - Jazzy
25
这并非一个错误,而是NaN在IEEE754标准下的行为。它是CPU实现的方式,也是在所有使用浮点数的编程语言中预期的行为。 - Tarmil
5
谨遵命!这其实非常有趣;我一直认为NaN不等式的怪异现象只发生在JavaScript中。 - Dan M
5
@atilkan - 这不是一个错误,而是一种特性。NaN不是一个值,它是某些出错情况的信号。此外,它还是一个信号,表明数学运算(包括===)将不会产生合理结果。+"foo" === +undefined不应该等于true,而 +"foo" === +"bar" 将更为糟糕。 - Justin Morgan
显示剩余8条评论

64

使用以下代码:

isNaN('geoff');

请参考isNaN() 的 MDN 文档

alert ( isNaN('abcd'));  // alerts true
alert ( isNaN('2.0'));  // alerts false
alert ( isNaN(2.0));  // alerts false

2
也许只有我一个人觉得,当var value = 0/0;var value2= String("123 131");创建NaN值时,NaN的概念变得混乱了,而像var value3 = "abcd";这样的东西也是NaN值。 - Nick Pineda
@NickPineda 为什么? - Sinjai

52

要测试一个属于数字类型的值是否为NaN,全局函数isNaN可以完成这项工作。

isNaN(any-Number);

对于适用于JS中所有类型的通用方法,我们可以使用以下任何一种:

对于ECMAScript-5用户:

#1
if(x !== x) {
    console.info('x is NaN.');
}
else {
    console.info('x is NOT a NaN.');
}

如果您正在使用ECMAScript-6:

#2
Number.isNaN(x);

为了在 ECMAScript 5 和 6 中保持一致,我们也可以使用这个 Number.isNaN 的 polyfill

#3
//Polyfill from MDN
Number.isNaN = Number.isNaN || function(value) {
    return typeof value === "number" && isNaN(value);
}
// Or
Number.isNaN = Number.isNaN || function(value) {     
    return value !== value;
}

请查看这个答案以获取更多细节。


7
感谢您不仅使用了 "isNan()",而且提供了完整详细的答案。当我在Google上找到这个问题时,这正是我想要的内容。 - mejdev
1
“……对于上述情况给出了错误的结果”我不会说是错误的,只是不同,因为全局的 isNaN 首先将参数转换为数字值。 - Felix Kling
1
@FelixKling 请查看更新的答案。谢谢。 - dopeddude
1
isNaN("lorem ipsum"); //在ES5中返回true,这让我很惊讶 - Nick Pineda
2
@NickPineda 感觉非常相同,但最终 MDN 可以这样解释: "当 isNaN 函数的参数不是 Number 类型时,该值首先被强制转换为 Number 类型。然后测试结果值以确定它是否为 NaN。" - dopeddude
基本区别在于一个检查是否为“非数字”,另一个检查是否不是特殊的NaN,因此Number.isNaN(“aa”)返回false,而isNaN(“aa”)返回true - jave.web

19

自从ES6起,Object.is(..) 是一个新的实用工具,可用于测试两个值的绝对相等性:

var a = 3 / 'bar';
Object.is(a, NaN); // true

下面的两个键是不同的。 var a = 0/0; console.log(a === NaN); // false console.log(Object.is(a, NaN)); // true - Ông Phùng

19

你应该使用全局的 isNaN(value) 函数调用,因为:

  • 它在不同浏览器中都有支持
  • 请参考 isNaN 的文档

示例:

 isNaN('geoff'); // true
 isNaN('3'); // false

我希望这可以对你有所帮助。


1
是的,isNaN('') //false 但是 parseInt('') //NaN。对于 null 也可以这么说。 - Silent Penguin

17

NaN是一个特殊的值,无法像那样进行测试。我想分享的有趣的事情是:

var nanValue = NaN;
if(nanValue !== nanValue) // Returns true!
    alert('nanValue is NaN');

这仅对NaN值返回true,并且是一种安全的测试方式。应该被包装在一个函数中或至少被注释,因为显然测试同一个变量不等于自己没有多少意义,呵呵。


1
这不是完全可靠的方法。根据规范,变量!==变量是检查NaN最可靠的方法。 - ALLSYED
1
请参见我上面的答案 ^ - Jazzy

14
JavaScript中的NaN代表“不是数字”,尽管它的类型实际上是数字。
typeof(NaN) // "number"

要检查变量是否为NaN值,我们不能简单地使用函数isNaN(),因为isNaN()存在以下问题,请参见下面的示例:
var myVar = "A";
isNaN(myVar) // true, although "A" is not really of value NaN

实际上发生的是,myVar隐式地被转换成了一个数字:

var myVar = "A";
isNaN(Number(myVar)) // true. Number(myVar) is NaN here in fact

实际上,这是有道理的,因为"A"实际上不是一个数字。但是我们真正想要检查的是myVar是否确切地等于NaN。

因此,isNaN()无法帮助。那么我们应该怎么做呢?

鉴于NaN是唯一一个与自身不相等的JavaScript值,因此我们可以使用!==来检查它是否等于自身。

var myVar; // undefined
myVar !== myVar // false

var myVar = "A";
myVar !== myVar // false

var myVar = NaN
myVar !== myVar // true

总之,如果一个变量!==它自己,那么这个变量的确是NaN值:

function isOfValueNaN(v) {
    return v !== v;
}

var myVar = "A";
isNaN(myVar); // true
isOfValueNaN(myVar); // false

10

要修复'1.2geoff'被解析的问题,只需使用Number()解析器。

因此,不要这样做:

parseFloat('1.2geoff'); // => 1.2
isNaN(parseFloat('1.2geoff')); // => false
isNaN(parseFloat('.2geoff')); // => false
isNaN(parseFloat('geoff')); // => true

这样做:

Number('1.2geoff'); // => NaN
isNaN(Number('1.2geoff')); // => true
isNaN(Number('.2geoff')); // => true
isNaN(Number('geoff')); // => true

编辑:我刚刚注意到另一个问题...传递给Number()的false值(以及true作为实际布尔值)返回为0!在这种情况下...每次都使用parseFloat。因此,退而求其次:

function definitelyNaN (val) {
    return isNaN(val && val !== true ? Number(val) : parseFloat(val));
}

这基本上覆盖了所有内容。我对它进行了基准测试,比lodash的_.isNaN慢90%,但那个函数并没有涵盖所有的NaN:

http://jsperf.com/own-isnan-vs-underscore-lodash-isnan

只是为了明确,我的函数照顾到了“Not a Number”这种人类文本解释,而lodash的函数则处理计算机直接解释的检查“NaN”的情况。


9

规则如下:

NaN != NaN

isNaN()函数存在的问题是,在某些情况下可能会返回意外的结果:

isNaN('Hello')      //true
isNaN('2005/12/12') //true
isNaN(undefined)    //true
isNaN('NaN')        //true
isNaN(NaN)          //true
isNaN(0 / 0)        //true

更好的检查值是否为NaN的方法是:
function is_nan(value) {
    return value != value
}

is_nan(parseFloat("geoff"))

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接