理清JS中等於(==)和全等(===)那些糾纏不清的關係

文章主要梳理了一下,不一樣類型的值在判斷是否相等時,存在的各類特殊關係,並給出判斷是否相等的可靠方法。面試

首先說明兩個關係:等於不必定全等,全等則必定等於;不等於則必定不全等,不全等不必定不等於。在文章中,能用全等的地方,等於也是必定成立的;等於不成立的地方,全等也必定不成立,相信你們都能理解,再也不做特殊說明。正則表達式

判斷0的符號

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

判斷undefinednull

仍是先看幾組關係:code

undefined === undefined // true
null === null // true
null == undefined // true
null === undefined // false複製代碼

因此,若是隻判斷一個變量值是否爲null或者變量未定義,只需使用「==」便可,可是若是要清楚地區分nullundefined,那就要進一步比較了。下面是兩個判斷nullundefined的方法: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;
}複製代碼

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複製代碼

文中不少對比的方法,其實均可以找到對應的對象方法實現值的對比,本文最主要的仍是提醒各位,在對比時,注意區分對比的是值仍是對象,若是目的是對比值是否相等,則要進一步轉化。另外,特別注意各種型的值在對比時存在的特殊狀況,以及特殊值之間的關係。

以上,但願對你有用。歡迎留言糾錯或補充。

相關文章
相關標籤/搜索