文章主要梳理了一下,不一样类型的值在判断是否相等时,存在的各类特殊关系,并给出判断是否相等的可靠方法。面试
首先说明两个关系:等于不必定全等,全等则必定等于;不等于则必定不全等,不全等不必定不等于。在文章中,能用全等的地方,等于也是必定成立的;等于不成立的地方,全等也必定不成立,相信你们都能理解,再也不做特殊说明。正则表达式
0 === -0
,可是它们不彻底相同,如何判断?markdown
先看几个关系:函数
Infinity === Infinity // true Infinity === -Infinity // false 1/-0 === -Infinity // true 1/0 === Infinity // true复制代码
因此有:spa
1/-0 === 1/-0 // true 1/0 === 1/0 // true 1/-0 === 1/0 //false复制代码
因此,0实际上是有符号的,可使用以上办法判断。prototype
undefined
和null
仍是先看几组关系:code
undefined === undefined // true null === null // true null == undefined // true null === undefined // false复制代码
因此,若是只判断一个变量值是否为null
或者变量未定义,只需使用“==”便可,可是若是要清楚地区分null
和undefined
,那就要进一步比较了。下面是两个判断null
和undefined
的方法:orm
Object.prototype.toString.call(null) === "[object, Null]" Object.prototype.toString.call(undefined) === "[object, Undefined]" // 还有一个关系注意一下,我看有些面试题会问到: typeof null === "object" typeof undefined === "undefined"复制代码
两个彻底同样的正则表达式实际上是不相等的:对象
var a = /[1-9]/; var b = /[1-9]/; a == b // false复制代码
由于a,b实际上是两个正则表达式对象,一样是引用类型的:内存
typeof a === "object" // true typeof b === "object" // true复制代码
若是咱们但愿可以比较两个正则表达式内容是否同样,而不关心内存地址,那么只须要比较两个表达式字符串是否相等便可:
var a = /[1-9]/; var b = /[1-9]/; '' + a === '' + b // true 注:'' + /[1-9]/ === '/[1-9]/'复制代码
这里须要区分字符串和字符串对象
若是是字符串,则直接使用“===
”符号判断便可:
var a = 'a string'; var b = 'a string'; a === b //true复制代码
可是,对于字符串对象(引用类型),直接对比时,对比的仍然是内存地址:
var a = new String('a string'); var b = new String('a string'); a == b // false复制代码
若是关注字符串内容是否相同,则能够将字符串对象转化为字符串,再进行比较:
var a = new String('a string'); var b = new String('a string'); '' + a == '' + b // true // 也可使用toString方法比较: a.toString() === b.toString() // true复制代码
因此,判断两个字符串内容是否相同,最可靠的办法是:
function isStringEqual(a, b) { return '' + a === '' + b; }复制代码
一样须要区分数值和数值对象:
var a = new Number(5); var b = new Number(5); // 直接对比时不相等 a == b //false // 使用+符号,转化成数值的对比 +a === +b //true复制代码
可是,有一个特殊的值必须特殊对待,即NaN
,它也是Number
类型的
Object.prototype.toString.call(NaN) // "[object Number]" typeof NaN // "number"复制代码
同时,它的以下关系致使了以上判断数值是否相等的方法出现了例外:
NaN == NaN //false +NaN == +NaN // false 注:+NaN仍是NaN复制代码
如何在两个数值都是NaN
的状况下判断二者是相等的呢?看一个命题:对于任意非NaN
的数值对象或数值(a),+a === +a
始终成立,假如该等式不成立,则a即为NaN
。因此,若是已知a为NaN
,如何在b也是NaN
时,但愿判断二者是相等的呢?
if(+a !== +a) return +b !== +b;复制代码
解释以下:
假设a为NaN
,判断条件成立,若是b也是NaN
,返回语句的表达式成立,返回true
,表示二者相等(都是NaN
);若是b不是NaN
,返回语句的表达式不成立,返回false
,表示二者不相等。
将以上判断的逻辑整合为一个判断函数,即:
function isNumberEqual(a, b) { if (+a !== +a) return +b !== +b; // 处理特殊状况 return +a === +b; }复制代码
对象的对比也不能直接使用等号判断,咱们仍是只关心日期值是否相同,因此,将日期转化为毫秒数值,而后对比数值是否相同
var a = new Date('2017-9-7'); var b = new Date('2017-9-7'); a == b //false +a === +b //true 注:+a的值为1504713600000,即,对应2017.9.7 00:00:00的毫秒数 效果和使用getTime()方法对比同样 a.getTime() === b.getTime() // true复制代码
对象不能直接对比,故,将布尔值转化为数值,而后对比
var a = new Boolean('123'); var b = new Boolean('123'); a == b //false +a === +b //true // 注: 布尔值为真,前面加“+”,转化为数值1,为假则转为0复制代码
文中不少对比的方法,其实均可以找到对应的对象方法实现值的对比,本文最主要的仍是提醒各位,在对比时,注意区分对比的是值仍是对象,若是目的是对比值是否相等,则要进一步转化。另外,特别注意各种型的值在对比时存在的特殊状况,以及特殊值之间的关系。
以上,但愿对你有用。欢迎留言纠错或补充。