为什么在JS中,isNaN(null)== false?
JS中的这段代码给了我一个弹出窗口,说"我认为null是一个数字",这让我感到有些不安。我想念什么?
if (isNaN(null)) { alert("null is not a number"); } else { alert("i think null is a number"); }
我正在使用Firefox3. 那是浏览器错误吗?
其他测试:
null == NaN; // false isNaN("text"); // true NaN == "text" // false
因此,问题似乎不是与NaN的精确比较?
编辑:现在问题已得到解答,我已经整理了帖子以为存档提供更好的版本。但是,这会引起一些评论甚至答案有些难以理解。不要怪他们的作者。我更改的内容包括:
- 删除了一条说明,说我最初是通过恢复标题的含义来弄乱标题的
- 较早的答案表明,我还没有足够清楚地说明为什么我认为这种行为很怪异,因此我添加了检查字符串并进行手动比较的示例。
解决方案
Null不是NaN,字符串也不是NaN。 isNaN()仅测试我们是否确实具有NaN对象。
我不太确定何时使用JS,但是我在其他语言中也见过类似的情况,这通常是因为该函数仅检查null是否完全等于NaN(即null === NaN将为false)。换句话说,并不是说null实际上是一个数字,而是null不是NaN。这可能是因为两者在JS中的表示方式不同,因此它们将不完全相同,就像9!=='9'一样。
我相信代码试图问" x是数字吗?"这里的具体情况是x = null。函数isNaN()
可以用来回答这个问题,但是从语义上讲,它专门指的是值NaN
。从Wikipedia中获取" NaN":
NaN (Not a Number) is a value of the numeric data type representing an undefined or unrepresentable value, especially in floating-point calculations.
在大多数情况下,我们认为答案为"是否为空数字?"应该没有。但是,isNaN(null)== false在语义上是正确的,因为null并非NaN。
这是算法的解释:
函数isNaN(x)尝试将传递的参数转换为number1(等效于Number(x)),然后测试该值是否为NaN。如果参数无法转换为数字,则Number(x)将返回NaN 2. 因此,如果将参数x转换为数字,则返回NaN,则返回true;否则,返回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.
这确实令人不安。这是我测试的一组值:
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
(我的其他评论采用了一种实用的方法。这是理论方面。)
我查找了Javascript实现的ECMA 262标准。他们对isNan的规范:
Applies ToNumber to its argument, then returns true if the result is NaN, and otherwise returns false.
第9.3节指定了" ToNumber"的行为(它不是可调用的函数,而是类型转换系统的组成部分)。总结表,某些输入类型可以产生NaN。这些是"未定义"类型,"数字"类型(但仅是值" NaN"),任何原始表示为" NaN"的对象以及任何无法解析的"字符串"。这样就留下了undefined,NaN,new Number(NaN)和大多数字符串。
当传递给" ToNumber"时,任何产生" NaN"作为输出的此类输入,当被提供给" isNaN"时,都会产生" true"。由于" null"可以成功转换为数字,因此不会产生" true"。
这就是为什么。
笔记:
"1" == 1 // true "1" === 1 // false
==运算符会进行类型转换,而===则不会。
道格拉斯·克罗克福德(Douglas Crockford)的网站Yahoo! JavaScript传播者,是此类资源的绝佳资源。