文章主要梳理了一下,不同型別的值在判斷是否相等時,存在的各種特殊關係,並給出判斷是否相等的可靠方法。
首先說明兩個關係:等於不一定全等,全等則一定等於;不等於則一定不全等,不全等不一定不等於。在文章中,能用全等的地方,等於也是一定成立的;等於不成立的地方,全等也一定不成立,相信大家都能理解,不再作特殊說明。
判斷0的符號
0 === -0
,但是它們不完全相同,如何判斷?
先看幾個關係:
Infinity === Infinity // true
Infinity === -Infinity // false
1/-0 === -Infinity // true
1/0 === Infinity // true複製程式碼
所以有:
1/-0 === 1/-0 // true
1/0 === 1/0 // true
1/-0 === 1/0 //false複製程式碼
所以,0其實是有符號的,可以使用以上辦法判斷。
判斷undefined
和null
還是先看幾組關係:
undefined === undefined // true
null === null // true
null == undefined // true
null === undefined // false複製程式碼
所以,如果只判斷一個變數值是否為null
或者變數未定義,只需使用“==”即可,但是如果要清楚地區分null
和undefined
,那就要進一步比較了。下面是兩個判斷null
和undefined
的方法:
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;
}複製程式碼
Date物件對比
物件的對比也不能直接使用等號判斷,我們還是隻關心日期值是否相同,所以,將日期轉化為毫秒數值,然後對比數值是否相同
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複製程式碼
文中很多對比的方法,其實都可以找到對應的物件方法實現值的對比,本文最主要的還是提醒各位,在對比時,注意區分對比的是值還是物件,如果目的是對比值是否相等,則要進一步轉化。另外,特別注意各型別的值在對比時存在的特殊情況,以及特殊值之間的關係。
以上,希望對你有用。歡迎留言糾錯或補充。