1 关于 NaN
当算术运算符返回一个未定义或其无法表示的值(除 Infinity 与 - Infinity),或不能将非数值类型强制转换为数值时,就会产生 NaN,表示不是一个有效数字,not a number。
NaN 是一个全局对象属性,初始值是 NaN,和 Number.NaN 相同。是 number 类型。
与 JavaScript 中其他值不同的是, 不能通过相等操作符( == 和 === )等来判断数据是否是 NaN,因为 NaN 不与任何值相等,包括其自身。
NaN === NaN // false
Number.NaN === NaN // false
1 === NaN // false
'1' === NaN // false
2 isNaN() 的必要性
由于 NaN
通过 ==
、 !=
、 ===
、以及 !==
与其他任何值及其他 NaN
值比较都不相等。故需使用 isNaN() 来判断值是否是 NaN。
一个 isNaN
的 polyfill 理解:
const isNaN = value => {
const x = Number(value)
return x !== x
}
isNaN 方法通过 Number() 隐式的将值进行转换后进行比较。
isNaN(NaN) // true
isNaN(undefined) // true Number(undefined) NaN
isNaN({}) // true Number({}) NaN
isNaN('s') // true Number('s') NaN
isNaN([]) // false Number([]) === 0
isNaN(1) // false
isNaN(new Date()) // false Number(new Date()) 1597233148879
isNaN('') // false Number('') === 0
isNaN(false) // false Number(false) === 0
isNaN(null) // false Number(null) === 0
3 isNaN() 的缺陷
如果 isNaN
函数的参数不是 Number
类型, isNaN
函数会首先尝试将这个参数通过 Number()
强制转换为数值,然后才会对转换后的结果进行判断。对于 undefined、{} 、非数字字符串等值,在强制类型转换失败,得到 NaN 后判断为 true。但其实其并不是特殊值 NaN。
实际上, isNaN()
得到的结果是被测值在被强制转换为数值后,是否不是一个数。并没有完全达到判断是否是 NaN
这一特殊值的目的。
单纯使用
x !== x
来判断 NaN 比 isNaN() 更加可靠。
4 isNaN() 的特殊行为
isNaN() 并非一无是处,由于 isNaN() 基于 Number() 的强制类型转换,所以:
- 如果
isNaN(value)
返回的是false
,那么value
在任何算数表达式中都不会使表达式等于NaN
- 如果返回
true
,value
会使所有算数表达式返回NaN
。
可以利用这一特殊行为来检测函数参数的可运算性(可以下像 number 一样进行加减乘除等运算)。如果不可运算,则可赋予这个参数一个默认的值或其他合适的内容。这样,就可以得到一个隐式转换参数值的函数。
5 Number.isNaN() 的改进
如 3 isNaN() 的缺陷
中所述,Number
提供了一种更稳妥的方法判断数据是否是 NaN
。
一个 Number.isNaN
的 polyfill 理解:
Number.isNaN = value => {
return typeof value === 'number' && isNaN(value)
}
可以看出 polyfill
理解中 加入了 number
类型判断。
实际中
Number.isNaN()
不会自行将参数转换成数字。
Number.isNaN(NaN); // true
Number.isNaN(Number.NaN) // true
Number.isNaN(0 / 0) // true
Number.isNaN(undefined) // false
Number.isNaN({}) // false
Number.isNaN('s') // false
Number.isNaN() 只有在参数是值为 NaN
的数字时,才会返回 true
。
即 Number.isNaN()
判断的是被测值是否是 NaN
这一特殊值。
6 参考资料
[1] [MDN] NaN
[3] [MDN] isNaN
网友评论