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

时间:2008-09-22 15:32:27

标签: javascript

JS中的这段代码给了我一个弹出窗口“我认为null是一个数字”,我觉得有点令人不安。我错过了什么?

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

我正在使用Firefox 3.这是一个浏览器错误吗?

其他测试:

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

那么,问题似乎不是与NaN的精确比较?

编辑:现在问题已经回答了,我已经清理了我的帖子,以便为存档提供更好的版本。然而,这使得一些评论甚至一些答案有点难以理解。不要责怪他们的作者。我改变的是:

  • 删除了一条说明,说我首先通过恢复其含义搞砸了标题
  • 之前的答案显示我没有说清楚为什么我认为这种行为很奇怪,所以我添加了检查字符串并进行手动比较的示例。

9 个答案:

答案 0 :(得分:101)

我相信代码试图问,“x是数字吗?”这里的具体案例为x = null。函数isNaN()可用于回答此问题,但从语义上讲,它特指值NaN。来自维基百科NaN

  

NaN( N ot a N umber)是表示未定义或不可表示的值的数值数据类型的值,尤其是在浮动时点计算。

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

以下是算法解释:

函数isNaN(x)尝试将传递的参数转换为数字 1 (相当于Number(x)),然后测试值是否为{{1 }}。如果参数无法转换为数字,NaN将返回Number(x) 2 。因此,如果将参数NaN转换为数字会导致x,则返回true;否则,它返回false。

因此,在特定情况NaN中,x = null转换为数字0,(尝试评估null并看到它返回0,)并且Number(null)返回false 。只有数字的字符串可以转换为数字,而isNaN也返回false。无法转换为数字的字符串(例如isNaN(0))会导致'abcd'返回true,特别是因为isNaN('abcd')返回Number('abcd')

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

对于问题中显示的看似不一致的相等性测试,NaN的行为被指定为任何比较NaN都是假的,无论其他操作数如何,包括x == NaN本身 1

答案 1 :(得分:20)

我自己也遇到了这个问题。

对我来说,使用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]

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

这对我来说似乎更好。

答案 2 :(得分: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只是已定义而不是数字,在这种情况下它的工作正常 - 只是带有误导性的名称。)

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

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

答案 3 :(得分:7)

(我的另一个评论采用了实用的方法。这是理论方面。)

我查找了ECMA 262 standard,这是Javascript实现的。他们对isNan的规范:

  

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

9.3节指定ToNumber的行为(它不是可调用函数,而是类型转换系统的一个组件)。总结该表,某些输入类型可以产生NaN。这些是类型undefined,类型number(但只有值NaN),其基本表示为NaN的任何对象,以及任何无法解析的string 。这会留下undefinedNaNnew Number(NaN)和大多数字符串。

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

这就是原因。

答案 4 :(得分:5)

Null不是NaN,字符串也不是NaN。 isNaN()只测试你是否真的有NaN对象。

答案 5 :(得分:1)

我不确定JS是什么,但我在其他语言中看到了类似的东西,通常是因为该函数只检查null是否与NaN完全相等(即null === NaN将为false )。换句话说,它不是认为null实际上是一个数字,而是null而不是NaN。这可能是因为两者在JS中的表示方式不同,因此它们不会完全相同,就像9!=='9'一样。

答案 6 :(得分:1)

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

并查看The abstract operation ToNumber convertion table。因此内部js引擎评估ToNumber(Null)+0,最后isNaN(null)false

答案 7 :(得分:0)

注意:

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

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

Douglas Crockford's website,雅虎! JavaScript传播者,对于像这样的东西来说是一个很好的资源。

答案 8 :(得分:-1)

(NaN == null) // false
(NaN != null) // true

虽然很有趣:

(NaN == true)  // false
(NaN == false) // false
(NaN)          // false
(!NaN)         // true

(NaN == false)(!NaN) 不是一样的吗?