浅谈 JS 中 isNaN() 与 Number.isNaN()

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
  • 如果返回 truevalue 会使所有算数表达式返回 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

[2] [MDN] Number.NaN()

[3] [MDN] isNaN

[4] [MDN] Number.isNaN()

你可能感兴趣的:(浅谈 JS 中 isNaN() 与 Number.isNaN())