Javascript中有一个特殊的对象:
NaN
,它是「not a number」的缩写。总结了以下几点需要注意,如有错误,烦请指正:P
1. Javascript中返回NaN的情况
就目前所学来看,以下两种情况会返回NaN:
-
表达式计算:
一个表达式中如果有减号 (-)、乘号 (*) 或 除号 (/) 等运算符时,JS 引擎在计算之前,会试图将表达式的每个分项转化为Number
类型(使用 Number()做转换)。如果转换失败,表达式将返回 NaN 。
一句话理解:任何数除以、减、乘非数值(undefined、string、object)时,都会直接返回NaN
。
100 - '2a' ; // NaN
'100' / '20a'; // NaN
'20a' * 5 ; // NaN
undefined / 5; // NaN
undefined * "hello" // NaN
-
类型转换失败:
使用parseInt
,parseFloat
或Number
将一个非数字的值转化为数字时,表达式返回 NaN
"abc" - 3 // NaN
parseInt("abc") // NaN
parseFloat("abc") //NaN
Number("abc") //NaN
NaN带来的坑
陷阱1:typeof NaN // 返回number
这种情况下返回了number。
在JS中,整数和浮点数都统称为Number,除此之外,还有一个特殊的数值类型就是NaN
。他不是一个数字,而是一种数值类型,这也解释了typeof NaN // 返回number
。
陷阱2:NaN == NaN // 返回false
无论相等还是全等,NaN与自身比较都返回false
!
因为NaN
表示一个无法表示的值,而有很多方法来表示一个非数字,所以一个非数字不会等于另一个为NaN的非数字。比如0/0返回NaN,0/'fail'也返回NaN,而0/0 != 0/’fail’,所以NaN == NaN返回false。
陷阱3:判断一个值是否为NaN
如上,==
,===
均不能用来判断一个值是否是NaN。必须使用Number.isNaN()
或isNaN
函数来检验,下面我们来看下他们的用法。
isNaN()
通常我们用isNaN
来判断一个值是否是NaN
,如下
isNaN(NaN) // true
isNaN(undefined) // true
isNaN({}) // true
isNaN(true) // false,为1
isNaN(null) // false,为0
isNaN("") // false ,为0
isNaN(" ") // false,带空格的字符串转换为数字为0
isNaN([]) // false,空数组转换为数字为0
isNaN()
接收一个参数,参数可以为任意数据类型。如果接收的参数是数字类型,返回false;如果是其他类型(除了数字的任何其他类型),则返回true;
- 若接收的参数为数字类型,返回
false
,表示不是NaN
。 - 若参数为非数字类型,会通过
toNumber()
将值强制转换为数值,再进行判断。 - 如接受的参数是空,比如[](空数组)、“”(空字符串)、null等,会在过程中转换为数字类型的0,从而返回false。
如下代码,在调用isNaN()
时,遇到字符串会强制进行隐式转换。
isNaN("1"); // false "1" 被转化为数字 1,因此返回false
isNaN("Hello World"); // true "Hello World" 被隐式转化成数字`NaN`
总结一下isNaN()
的坑:
如果传入的参数不是number
类型,isNaN()
会尝试将参数转换为数值,然后再对转换后的数值进行判断。因此,就算对于能够被转换为数值的数据类型来说(要特别注意,空字符串、布尔、null、空数组会返回0
,布尔值会返回对应数值),返回false
值也是反直觉的。
说到底,其实是Javascript强制类型转换的坑啊!
ES6新特性 Number.isNaN()
例如,空字符串就明显不是数值,但是还是返回了0,这是相当的反直觉的!
所以,我们能否不进行隐式转换来判断NaN
呢?答案是,可以的!
ES6引入了另一种判断方法来填坑——Number.isNaN(x)
。通过这个函数来检测x是否是一个非数值,这方法比isNaN()
更为可靠。只有在参数是真正的数值类型,且判断后值为 NaN 的时候才会返回 true。
Number.isNaN(NaN) // true,NaN既是数值类型,返回的又是NaN
Number.isNaN("NaN") // false,这里"NaN"是string,不是数字类型,所以直接返回false
Number.isNaN("hello") // false
isNaN("hello") // true,Number("hello")返回NaN,再判断isNaN(NaN) // true
Number.isNaN({}) // false
isNaN({}) // true,Number({})返回NaN,判断同上
Number.isNaN("") // false
isNaN("") // true
总的来说,Number.isNaN()
进行了更严格的判断。
网友评论