Appearance
14. isNaN 和 Number.isNaN
开局一张图,日常感叹 thanks for inventing js ~ 别急,看完就懂了。
isNaN()
我们都知道 NaN
是 JS 中一种特殊的 Number 类型,使用 ==
或 ===
都无法进行判断和比较。
js
NaN == NaN // false
NaN === NaN // false
1
2
2
JS 提供了一种判断 NaN
的方法,就是使用 isNaN
函数。(这里指全局下的 isNaN 方法,浏览器中就是 Window.isNaN
)
js
isNaN(NaN) // true
isNaN(1 / 'a') // false
1
2
2
以上都很好理解,1 / 'a'
的计算结果就是 NaN
,所以都是 true
。但是下面这几个例子可能会让你感到疑惑,明明是判断 NaN
的,传入了非 NaN 值,结果居然返回了 true
。
js
isNaN('12a') // true
isNaN('aaa') // true
isNaN(undefined) // true
1
2
3
2
3
下面这个例子可能会让你更加一头雾水。
js
isNaN([]) // false
isNaN([1]) // false
isNaN([1, 2]) // true
1
2
3
2
3
什么?同样是数组,为什么会有不同的表现?再次重申:“计算机没有黑魔法”,在 JS 里面就是,凡是遇到诡异行为就去查看 MDN 文档或者 ES 规范。这里直接给出 ES 规范中的定义:
Link: https://tc39.es/ecma262/#sec-isnan-number
It performs the following steps when called:
- Let num be ToNumber(number).
- If num is NaN, return true.
- Otherwise, return false.
这里直接给出解释了,isNaN
的第一步是触发 ToNumber
,这是 JS 底层的一个方法,也就是所谓的隐式强制转换,你可以理解为 Number()
。
ToNumber: https://tc39.es/ecma262/#sec-tonumber
上面的例子也可以解释了:
js
isNaN('12a') // true,'12a' 试图被转换为数字,但是格式不对,因此是 NaN
isNaN('aaa') // true,同上
isNaN(undefined) // true,同上
isNaN([]) // false,[] => '' => 0 => 0 is not NaN
isNaN([1]) // false,[1] => '1' => 1 => 1 is not NaN
isNaN([1, 2]) // true, [1, 2] => '1,2' => NaN
1
2
3
4
5
6
7
2
3
4
5
6
7
Number.isNaN()
上述规则虽然诡异,但其实也可以理解,毕竟 'aaa'
这种值确实 “不是一个数字”,符合 NaN
的语义 “not a number”。但有时候我们需要更加纯粹的判断 NaN 的更可靠的方法,于是 ES6 中 Number.isNaN
就出现了。
Number.isNaN()
直接判断传入的值是否为 NaN
,而不会对其去进行强制转换,是更可靠的方式。
js
Number.isNaN(NaN) // true
Number.isNaN('12a') // false
Number.isNaN('aaa') // false
Number.isNaN(undefined) // false
Number.isNaN([]) // false
Number.isNaN([1]) // false
Number.isNaN([1, 2]) // false
1
2
3
4
5
6
7
2
3
4
5
6
7
还是摘录 ES 规范中的定义:
Link: Number.isNaN(number)
This function performs the following steps when called:
- If number is not a Number, return false.
- If number is NaN, return true.
- Otherwise, return false.
Number.isNaN 首先判断是否为 number 类型,如果不是直接返回 false
,然后判断是否为 NaN
。所以它的一种 polufill 可以是:
js
Number.isNaN = Number.isNaN || function(value) {
return typeof value === 'number' && value !== value
}
1
2
3
2
3