你不知道的 JavaScript 系列中( 11 ) - 特殊数值 NaN
如果数学运算的操作数不是数字类型或者无法解析为常规的十进制或十六进制数字,就无法返回一个有效的数字,这种情况下返回值为 NaN。NaN 意指 “不是一个数字”,这个名字容易引起误会,“无效数值” “失败数值” 或者 “坏数值” 可能更准确些。
var a = 2 / 'foo'; // NaN typof a === 'number'; // true
换句话说 “不是数字的数字” 仍然是数字类型。
检测变量的值是否为 NaN,可以直接和 NaN 进行比较,就像比较 null 和 undefined 一样,实则不然。
var a = 2 / 'foo'; a == NaN; // false a === NaN; // false
NaN 是一个特殊值,它和自身不相等,是唯一一个非自反(即 x === x 不成立)的值。而 NaN != NaN 为 true。既然我们无法对 NaN 进行比较,那应该怎么判断它呢?
var a = 2 / 'foo'; isNaN(a); // true
很简单,可以使用内置工具函数 isNaN(...) 来判断一个值是否是 NaN。然后 isNaN(...) 有一个严重的缺陷,它的检查方式过于死板,就是 “检查参数是否不是 NaN,也不是数字”。但是这样做的结果并不太准确:
var a = 2 / 'foo'; var b = 'foo'; a; // NaN b; // 'foo' window.isNaN(a); // true window.isNaN(b); // true ——晕
很明显 foo 不是一个数字,但是它也不是 NaN,这个 bug 自 JS 问世以来一直在。从 ES6 开始我们可以使用工具函数 Number.isNaN(...)。ES6 之前的 polyfill:
if (!Number.isNaN) { Number.isNaN = function(n) { return typeof n === 'number' && window.isNaN(n) } } var a = 2 / 'foo'; var b = 'foo'; Number.isNaN(a); // true Number.isNaN(b); // false ——好
实际上还有一个更简单的方法,即利用 NaN 不等于自身这个特点,NaN 是 JS 中唯一一个不等于自身的值
if (!Number.isNaN) { Number.isNaN = function(n) { return n !== n; } }
很多程序都可能存在 NaN 方面的问题,所以应该尽量使用 Number.isNaN(...) 这样可靠的方法,如果仍然在代码中使用 isNaN(...),那么程序迟早会出现 bug