JS中的这段代码给了我一个弹出窗口,说"我认为null是一个数字",我觉得有点令人不安.我错过了什么?
if (isNaN(null)) {
alert("null is not a number");
} else {
alert("i think null is a number");
}
我正在使用Firefox 3.这是一个浏览器错误吗?
其他测试:
console.log(null == NaN); // false
console.log(isNaN("text")); // true
console.log(NaN == "text"); // false
那么,问题似乎不是与NaN的精确比较?
编辑:现在问题已经得到解答,我已经清理了我的帖子,以便为存档提供更好的版本.然而,这使得一些评论甚至一些答案有点难以理解.不要责怪他们的作者.我改变的事情包括:
删除了一条说明,说我首先通过恢复其含义搞砸了标题
早期的答案显示我没有明确说明为什么我认为这种行为很奇怪,所以我添加了检查字符串并进行手动比较的示例.
Glenn Moss.. 108
我相信代码试图问,"是x
数字吗?" 具体案例在这里x = null
.该函数isNaN()
可用于回答这个问题,但从语义上讲,它特指的是该值NaN
.来自维基百科NaN
:
NaN(N ot a N umber)是表示未定义或不可表示的值的数值数据类型的值,尤其是在浮点计算中.
在大多数情况下,我们认为"无效数字"的答案是什么?应该是没有.但是,isNaN(null) == false
在语义上是正确的,因为null
不是NaN
.
这是算法解释:
该函数isNaN(x)
尝试将传递的参数转换为数字1(相当于Number(x)
),然后测试该值是否为NaN
.如果参数无法转换为数字,Number(x)
则返回NaN
2.因此,如果将参数转换为x
数字NaN
,则返回true; 否则,它返回false.
所以在特定情况下x = null
,null
转换为数字0,(尝试评估Number(null)
并看到它返回0,并isNaN(0)
返回false).只有数字的字符串可以转换为数字,而isNaN也返回false.'abcd'
无法转换为数字的字符串(例如)将导致isNaN('abcd')
返回true,特别是因为Number('abcd')
返回NaN
.
除了这些明显的边缘情况之外,返回NaN的标准数值原因如0/0.
对于问题中显示的看似不一致的相等性测试,NaN
指定的行为使得任何比较x == NaN
都是假的,而不管其他操作数,包括NaN
它自己1.
我相信代码试图问,"是x
数字吗?" 具体案例在这里x = null
.该函数isNaN()
可用于回答这个问题,但从语义上讲,它特指的是该值NaN
.来自维基百科NaN
:
NaN(N ot a N umber)是表示未定义或不可表示的值的数值数据类型的值,尤其是在浮点计算中.
在大多数情况下,我们认为"无效数字"的答案是什么?应该是没有.但是,isNaN(null) == false
在语义上是正确的,因为null
不是NaN
.
这是算法解释:
该函数isNaN(x)
尝试将传递的参数转换为数字1(相当于Number(x)
),然后测试该值是否为NaN
.如果参数无法转换为数字,Number(x)
则返回NaN
2.因此,如果将参数转换为x
数字NaN
,则返回true; 否则,它返回false.
所以在特定情况下x = null
,null
转换为数字0,(尝试评估Number(null)
并看到它返回0,并isNaN(0)
返回false).只有数字的字符串可以转换为数字,而isNaN也返回false.'abcd'
无法转换为数字的字符串(例如)将导致isNaN('abcd')
返回true,特别是因为Number('abcd')
返回NaN
.
除了这些明显的边缘情况之外,返回NaN的标准数值原因如0/0.
对于问题中显示的看似不一致的相等性测试,NaN
指定的行为使得任何比较x == NaN
都是假的,而不管其他操作数,包括NaN
它自己1.
我自己也遇到过这个问题.
对我来说,使用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]
(我根据输入对齐结果,希望它更容易阅读.)
这对我来说似乎更好.
这确实令人不安.这是我测试的一系列值:
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
(我的另一个评论采用了实用的方法.这是理论方面.)
我查找了ECMA 262标准,这是Javascript实现的标准.他们对isNan的规范:
将ToNumber应用于其参数,如果结果为NaN则返回true,否则返回false.
9.3节规定了ToNumber
(不是可调用函数,而是类型转换系统的一个组件)的行为.总结该表,某些输入类型可以产生NaN.这些是类型undefined
,类型number
(但只是值NaN
),其基本表示形式的任何对象NaN
,以及任何string
无法解析的对象.这树叶undefined
,NaN
,new Number(NaN)
,和大多数字符串.
任何这样的输入,产生NaN
传递给时作为输出ToNumber
将产生true
馈送到时isNaN
.既然null
可以成功转换为数字,就不会产生true
.
这就是原因.
Null不是NaN,字符串也不是NaN.isNaN()只测试你是否真的有NaN对象.