为什么在JS中,isNaN(null)== false?


129

JS中的这段代码给了我一个弹出窗口,说“我认为null是一个数字”,这让我感到有些不安。我想念什么?

if (isNaN(null)) {
  alert("null is not a number");
} else {
  alert("i think null is a number");
}

我正在使用Firefox3。那是浏览器错误吗?

其他测试:

console.log(null == NaN);   // false
console.log(isNaN("text")); // true
console.log(NaN == "text"); // false

因此,问题似乎不是与NaN的精确比较?

编辑:现在问题已经回答,我已经整理了帖子以为存档提供更好的版本。但是,这会引起一些评论甚至答案有些难以理解。不要怪他们的作者。我更改的内容包括:

  • 删除了一条说明,说我最初是通过恢复其含义来弄乱标题的
  • 较早的答案表明,我还没有足够清楚地说明为什么我认为该行为很怪异,因此我添加了检查字符串并进行手动比较的示例。

3
您不是说“为什么isNaN(null)== false”吗?
Matt Rogish

根据您的代码,如果isnan(null)表示“我认为null是数字”,则返回false(null不是“不是数字”)。
devinmoore's

Answers:


114

我相信代码试图问“是x数字吗?” 与这里的具体情况有关x = null。该函数isNaN()可用于回答此问题,但从语义上讲,它是专门指value NaN。从Wikipedia获得NaN

NaN( Ñ加时赛一个 Ñ棕土)是代表一个未定义的或不可表示的值,特别是在浮点运算的数值数据类型的值。

在大多数情况下,我们认为答案是“空数字?” 应该没有。但是,isNaN(null) == false在语义上是正确的,因为null不是NaN

这是算法说明:

该函数isNaN(x)尝试将传递的参数转换为数字1(等于Number(x)),然后测试该值是否为NaN。如果参数不能转换为数字,Number(x)将返回NaN2。因此,如果将参数转换为x数字NaN,则返回true;否则,返回true。否则,它返回false。

因此,在特定情况下x = nullnull将转换为数字0(尝试进行评估Number(null),看看它返回0),然后isNaN(0)返回false。只有数字的字符串可以转换为数字,isNaN也返回false。的字符串(例如,'abcd'不能被转换为数字)将导致isNaN('abcd')返回true,特别是因为Number('abcd')返回NaN

除了这些明显的边缘情况外,还返回NaN的标准数值原因,如0/0。

至于问题中显示的看似不一致的测试,NaN则指定的行为,使得任何比较x == NaN都是假的,而与其他操作数无关,包括NaN自身1


8
顺便说一句,NaN !== NaN。因此,我认为,说是不完全正确的,Number('abcd') == NaN因为Number('abcd')NaN但不等于NaN。我喜欢JavaScript。
nilfalse

是。我想传达的Number('abcd')是,NaN但我隐含地表示它对相等性进行测试,但事实并非如此。我将对其进行编辑。
Glenn Moss

我想知道为什么isNaN并且Number设计成这样吗?
timidboy 2014年

1
仅在(至少在这种情况下)该函数内发生null到的转换,0isNaN()函数强制执行其参数。
Glenn Moss 2015年

3
Number(null)== 0,但parseInt(null)== NaN喜欢JS
JoshBerke 2015年

31

我只是自己碰到这个问题。

对我来说,最好的使用isNaN的方式就像这样

isNaN(parseInt(myInt))

从上面以phyzome的例子,

var x = [undefined, NaN,     'blah', 0/0,  null, 0,     '0',   1,     1/0, -1/0,  Number(5)]
x.map( function(n){ return isNaN(parseInt(n))})
        [true,      true,    true,   true, true, false, false, false, true, true, false]

(我根据输入对齐了结果,希望它更易于阅读。)

这对我来说似乎更好。


1
如果myInt=“ 123d”,则无法使用。parseInt将“ 123d”转换为123,然后isNaN测试失败。
divesh premdeep

确实,如果您也想了解这种情况,我建议将我的答案与格伦的答案结合起来。看起来像这样isNaN(parseInt(str,10)) || isNaN(Number())。btw-对我来说,由于必须运行parseInt才能使用字符串的数值,因此允许将“ 123d”视为有效数字是可以的。但是,我认为也需要检测这种情况。
guy mograbi

8

(我的其他评论采用一种实用的方法。这是理论方面。)

我查找了Java所实现的ECMA 262标准。他们对isNan的规范:

将ToNumber应用于其参数,如果结果为NaN,则返回true,否则返回false。

第9.3节指定了行为ToNumber(不是可调用函数,而是类型转换系统的组件)。总结表,某些输入类型可以产生NaN。它们是type undefined,type number(但仅是value NaN),任何原始表示为的对象NaN以及任何string无法解析的对象。这叶undefinedNaNnew Number(NaN),和大多数字符串。

NaN传递给时ToNumber将作为输出产生的任何此类输入将true馈入时产生a isNaN。由于null可以成功转换为数字,因此不会产生true

这就是为什么。


7

这确实令人不安。这是我测试的一组值:

var x = [undefined, NaN, 'blah', 0/0, null, 0, '0', 1, 1/0, -1/0, Number(5)]

评估(在Firebug控制台中)为:

,NaN,blah,NaN,,0,0,1,Infinity,-Infinity,5

当我调用x.map(isNaN)(在每个值上调用isNaN)时,我得到:

true,true,true,true,false,false,false,false,false,false,false

总之,isNaN看起来很没用!(编辑:事实证明,isNaN仅在Number上定义,在这种情况下,它工作得很好-只是名称具有误导性。)

顺便说一下,这是这些值的类型:

x.map(function(n){return typeof n})
-> undefined,number,string,number,object,number,string,number,number,number,number

您认为NaN应该是什么意思?您认为NaN或测试方面有什么误导性?你为什么打扰?
Bekim Bacaj

好吧,这是8年前的事,但似乎让我感到不安的是:1)对于非Number类型的值,其结果不一致;以及2)对于非Number类型的值,其返回true。因为字符串实际上不是NaN。(另请参阅我的其他答案,这说明了为什么会发生这种情况。)
好好对待您的mods

5

Null不是NaN,字符串也不是NaN。isNaN()仅测试您是否确实具有NaN对象。


但是随后至少一个字符串被强制转换为NaN对象,因为isNaN(“ text”)返回true。
汉诺·菲茨

1

我不确定要使用JS,但是我在其他语言中也见过类似的情况,这通常是因为该函数仅检查null是否完全等于NaN(即null === NaN将为假)。换句话说,并不是说null实际上是一个数字,而是null不是NaN。这可能是因为两者在JS中的表示方式不同,所以它们将不完全相同,就像9!=='9'一样。


1

在ES5中,isNaN (number)如果参数强制为NaN ,则定义为返回true,否则返回false。

并参见抽象操作ToNumber转换表。所以它在内部js引擎评估ToNumber(Null)+0,然后最终isNaN(null)false


0

注意:

"1" == 1 // true
"1" === 1 // false

==运算符会进行类型转换,而===则不会。

Douglas Crockford的网站 Yahoo! JavaScript传播者,是此类资源的绝佳资源。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.