前言
本文和大家分享一个前几天写代码踩的坑,笔者在业务逻辑中需要对一个值进行 NaN 的判断,由于笔者的不严谨,使用了isNaN,从而引起了Bug,也正是因为这个,笔者才知道了 isNaN 和 Number.isNaN 的区别,如果你认为这俩没区别,觉得 isNaN 是历史遗留的全局变量,后面又加到 Number 上的话,建议你接着往下看。如果你知道他们的区别,可以划走了。👻
笔者将从以下两个方面来描述这个知识点:
- 什么是
NaN。 isNaN和Number.isNaN的区别是什么。
什么是NaN
JS 中的 NaN,是 Not a Number 的缩写,代表一个值 或者 一个表达式的值 不是一个数字。它有以下几个特点:
- 不等于任何其他值,包括它本身。这意味着
NaN与任何值的比较都会返回false,包括NaN本身。

- 它是全局作用域中的一个变量。
Number.NaN和NaN是同一个东西,有相同的特性,只不过一个是全局变量;一个是Number上的属性。但是它俩也不能划等号,毕竟NaN自己都不等于自己。NaN涉及数学运算,通常情况下都会返回NaN,但是还有例外,看下图:
NaN涉及关系比较(>,<,>=,<=)时,都返回false。
什么情况下会得到NaN呢?
- 显式将非
NumBer类型转为Number类型,比如Number('aaa')。 - 在调用一些需要数字类型参数的
API时,可能API内部会做转换,一旦无法转为数字,可能就返回了NaN,比如Math.abs('aaa')。 - 等等......
那在平时开发中,为了保证我们写的代码逻辑运行正常,就可能需要对 NaN 判断,接下来我们就来看下判断 NaN 的两个 API 有啥不同。
isNaN 和 Number.isNaN 的区别
首先,这俩 API 都能够用于判断 NaN,这一点从 API 的名字就能看出,然后各位看图总结不同的地方:
不同点:
Number.isNaN是直接拿参数与NaN去比,也就是说,你一定要传NaN进去才返回true。至于怎么比的,咱也不知道,反正不是===,因为NaN的特性------自己不等于自己。isNaN会先尝试将参数转换成数字,如果可以转换成数字,则返回false;否则返回true。
咱们不妨来讨论一下,Number.isNaN内部的实现,肯定不是:
js
Number.isNaN = (target) => target === NaN // 自己不等于自己
我猜可能是:
js
// 因为只有传 `NaN` 进去才返回 `true`,而 NaN 是 Number 类型
// 再加上 `NaN + '' === 'NaN'`
// 也许是对的
Number.isNaN = (target) => Object.prototype.toString.call(target) === '[object Number]' && target+'' === 'NaN'
总结
本文主要内容为:
NaN的特性isNaN和Number.isNaN的区别,一句话总结:Number.isNaN只有传NaN进去才返回true;isNaN传NaN或者不能转化为Number的都会返回true。
以后咱们还是不要使用isNaN为好!
如果本文对你有一点点帮助,点个赞支持一下吧,你的每一个【赞】都是我创作的最大动力 ^_^。