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

IT技术 javascript
2021-03-07 12:13:36

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 的精确比较?

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

  • 删除了一条说明我通过恢复其含义首先搞砸了标题的说明
  • 较早的答案表明我没有足够清楚地说明为什么我认为这种行为很奇怪,因此我添加了检查字符串并进行手动比较的示例。
6个回答

我相信代码试图问,“是x数字吗?” 与这里的具体情况x = null该函数isNaN()可用于回答这个问题,但在语义上它专门指的是 value NaN来自维基百科NaN

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

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

这是算法解释:

该函数isNaN(x)尝试将传递的参数转换为数字1(相当于Number(x)),然后测试该值是否为NaN如果参数不能转换为数字,Number(x)将返回NaN2因此,如果将参数转换为x数字的结果为NaN,则返回真;否则,它返回 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

是的。我想表达的Number('abcd')是,NaN但我暗示它测试是否相等,但事实并非如此。我会编辑它。
2021-04-17 12:13:36
请注意isNaN(undefined) === true
2021-04-24 12:13:36
顺便说一句,NaN !== NaN所以,我认为,说Number('abcd') == NaN因为Number('abcd')isNaN但不等于并不完全正确NaN我喜欢 JavaScript。
2021-04-26 12:13:36
nullto 0only的转换(至少在这种情况下)发生在isNaN()函数内,这会强制其参数。
2021-05-07 12:13:36
Number(null) == 0 但 parseInt(null) == NaN 喜欢 JS
2021-05-12 12:13:36

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

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

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

这对我来说似乎更好。

如果myInt="123d"将不起作用parseInt将“123d”转换为 123,然后isNaN测试失败
2021-04-17 12:13:36
确实,如果您也想捕捉这种情况,我建议将我的答案和 Glenn 的答案结合起来。看起来像这样isNaN(parseInt(str,10)) || isNaN(Number())顺便说一句 - 对我来说,因为我必须运行parseInt才能使用字符串的数值,所以允许将“123d”视为有效数字很好。但是,我认为也需要检测这种情况。
2021-05-15 12:13:36

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

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

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

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

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

这就是为什么。

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

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 或在测试中如此具有误导性?你为什么不安?
2021-04-23 12:13:36
嗯,这是 8 年前的事,但看起来我很不安,1) 对于非 Number 类型的值,它的结果不一致,2) 对于非 Number 类型的值,它总是返回 true。因为字符串实际上不是 NaN。(另请参阅我的其他答案,这解释了为什么会发生这种情况。)
2021-05-03 12:13:36

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

但是至少一个字符串被转换成一个 NaN 对象,因为 isNaN("text") 返回 true。
2021-04-19 12:13:36
“isNaN() 只是测试你是否真的有 NaN 对象” ——不,Number.isNaN这样做。isNaN将其参数强制为一个数字,然后检查它是否是一个NaN值。
2021-04-22 12:13:36