文章主要梳理了一下,不一樣類型的值在判斷是否相等時,存在的各類特殊關係,並給出判斷是否相等的可靠方法。面試
首先說明兩個關係:等於不必定全等,全等則必定等於;不等於則必定不全等,不全等不必定不等於。在文章中,能用全等的地方,等於也是必定成立的;等於不成立的地方,全等也必定不成立,相信你們都能理解,再也不做特殊說明。正則表達式
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複製代碼
文中不少對比的方法,其實均可以找到對應的對象方法實現值的對比,本文最主要的仍是提醒各位,在對比時,注意區分對比的是值仍是對象,若是目的是對比值是否相等,則要進一步轉化。另外,特別注意各種型的值在對比時存在的特殊狀況,以及特殊值之間的關係。
以上,但願對你有用。歡迎留言糾錯或補充。