寬鬆相等( == )與嚴格相等( === )

dapan發表於2021-09-09

基本規則

1、比較基本型別值的時候,如果兩個值的型別相同,就僅比較它們是否相等,此時,== 和 === 之間並沒有什麼不同;
2、如果型別不同,== 會將其中之一或兩者都轉換為相同的型別後再進行比較,而 === 不允許這樣的轉換髮生。
3、比較引用型別值的時候,只要兩個物件指向同一個值時即視為相等,不發生型別轉換,因此使用== 或者 === 都是一樣的。

*NaN 不等於 NaN,+0 等於 -0 需要特殊對待。

字串和數字之間的相等比較

考慮下面的例子:

var a = 1;
var b = "1";
console.log(a === b); //輸出:false
console.log(a == b); //輸出:true

因為沒有型別轉換,所以 a === b 為 false;
而 a == b 是寬鬆相等,即如果兩個值的型別不同,則對其中之一或兩者都進行型別轉換。ES5 規範定義了下面兩條具體的轉換規則:
(1) 如果 a 是數字,b 是字串,則返回 a == Number(b) 的結果;
(2) 如果 a 是字串,b 是數字,則返回 Number(a) == b 的結果。
根據規範,在進行 == 比較時,“1” 應該會被轉換為數字以便進行相等比較。

其他型別和布林型別之間的相等比較

考慮下面的例子:

var a = "520";
var b = true;
console.log(a == b); //輸出:false

我們可能覺得"520"應該會被轉換為 true ,然後和 b 進行比較,但實際情況並不是這樣的。ES5 規範對於布林值也定義了下面兩條轉換規則:
(1) 如果 a 是布林型別,則返回 Number(a) == b 的結果;
(2) 如果 b 是布林型別,則返回 a == Number(b) 的結果。
根據規範,在進行 == 比較時,true 被轉換為 1,而"520" 根據規則被轉換為 520,最後變成 1 == 520,結果為 false。

*這裡面有一個慣性思維要捋清,字串"520" 本身是可以被轉換為布林值 true ,但 “520” == true 這個表示式中,“520” 並沒有發生布林值的轉換(隱式或顯式轉換都沒有發生),而是 true 轉換為 1,“520” 轉換為 520。實際工作中,也要避免使用 == true 和 == false。

null 和 undefined 之間的相等比較

在 == 中,null 和 undefined 可以相互進行隱式型別轉換, null 和 undefined 相等(它們也與其自身也相等),除此之外與其他值都不相等。

例子:

var a = null;
var b;
console.log(a == b); //輸出:true
console.log(a == undefined); //輸出:true
console.log(b == null); //輸出:true

console.log(a == false); //輸出:false
console.log(b == false); //輸出:false
console.log(a == ""); //輸出:false
console.log(b == ""); //輸出:false
console.log(a == 0); //輸出:false
console.log(b == 0); //輸出:false

物件和非物件之間的相等比較

關於物件和基本型別之間的相等比較,ES5 做了如下規定:
(1) 如果 a 是字串或數字,b 是物件,則返回 a == ToPrimitive(b) 的結果;
(2) 如果 a 是物件,b 是字串或數字,則返回 ToPromitive(a) == b 的結果。

*如果是物件和布林值之間的相等比較,布林值會先被轉換為數字。
*ToPrimitive() ,即物件的隱式轉換:首先呼叫 valueOf() 方法,然後透過 toString() 方法將返回值轉換為字串。具體可參考:

例子:

var a = "520";
var b = [520];
console.log(a === b); //輸出:false
//[520] 轉換過程:[520] => "520" => 520
console.log(a == b); //輸出:true

如有錯誤,歡迎指正,本人不勝感激。

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/758/viewspace-2822092/,如需轉載,請註明出處,否則將追究法律責任。

相關文章