天天看點

js裡==和===有什麼差別?

JavaScript 提供兩種相等運算符:==和===。

簡單說,它們的差別是相等運算符 == 比較兩個值是否相等,嚴格相等運算符 === 比較它們是否為“同一個值”。如果兩個值不是同一類型,嚴格相等運算符 === 直接傳回false,而相等運算符 == 會将它們轉換成同一個類型,再用嚴格相等運算符進行比較。

嚴格相等運算符===

嚴格相等運算符的規則如下:

1、不同類型的值

如果兩個值的類型不同,直接傳回false。

示例如下:

1 === "1" // false
true === "true" // false      

2、同一類型的原始類型值

同一類型的原始類型的值(數值、字元串、布爾值)比較時,值相同就傳回true,值不同就傳回false。

1 === 0x1 // true      

上面代碼比較十進制的1與十六進制的1,因為類型和值都相同,傳回true。

需要注意的是,NaN與任何值都不相等(包括自身)。另外,正0等于負0。

NaN === NaN  // false
+0 === -0 // true      

3、複合類型值

兩個複合類型(對象、數組、函數)的資料比較時,不是比較它們的值是否相等,而是比較它們是否指向同一個位址。

{} === {} // false
[] === [] // false
(function () {} === function () {}) // false      

上面代碼分别比較兩個空對象、兩個空數組、兩個空函數,結果都是不相等。原因是對于複合類型的值,嚴格相等運算比較的是,它們是否引用同一個記憶體位址,而運算符兩邊的空對象、空數組、空函數的值,都存放在不同的記憶體位址,結果當然是false。

如果兩個變量引用同一個對象,則它們相等。

var v1 = {};
var v2 = v1;
v1 === v2 // true      

注意,對于兩個對象的比較,嚴格相等運算符比較的是位址,而大于或小于運算符比較的是值。

new Date() > new Date() // false
new Date() < new Date() // false
new Date() === new Date() // false      

上面的三個表達式,前兩個比較的是值,最後一個比較的是位址,是以都傳回false。

4、undefined 和 null

undefined和null與自身嚴格相等。

undefined === undefined // true
null === null // true      

由于變量聲明後預設值是undefined,是以兩個隻聲明未指派的變量是相等的。

var v1;
var v2;
v1 === v2 // true      

5、嚴格不相等運算符

嚴格相等運算符有一個對應的“嚴格不相等運算符”(!==),它的算法就是先求嚴格相等運算符的結果,然後傳回相反值。

1 !== '1' // true      

相等運算符==

相等運算符用來比較相同類型的資料時,與嚴格相等運算符完全一樣。

比較不同類型的資料時,相等運算符會先将資料進行類型轉換,然後再用嚴格相等運算符比較。類型轉換規則如下。

1、原始類型的值

原始類型的資料會轉換成數值類型再進行比較。

1 == true // true
// 等同于 1 === Number(true)

0 == false // true
// 等同于 0 === Number(false)

2 == true // false
// 等同于 2 === Number(true)

2 == false // false
// 等同于 2 === Number(false)

'true' == true // false
// 等同于 Number('true') === Number(true)
// 等同于 NaN === 1

'' == 0 // true
// 等同于 Number('') === 0
// 等同于 0 === 0

'' == false  // true
// 等同于 Number('') === Number(false)
// 等同于 0 === 0

'1' == true  // true
// 等同于 Number('1') === Number(true)
// 等同于 1 === 1

'\n  123  \t' == 123 // true
// 因為字元串轉為數字時,省略前置和後置的空格      

上面代碼将字元串和布爾值都轉為數值,然後再進行比較。

2、對象與原始類型值比較

對象(這裡指廣義的對象,包括數組和函數)與原始類型的值比較時,對象轉化成原始類型的值,再進行比較。

[1] == 1 // true
// 等同于 Number([1]) == 1

[1] == '1' // true
// 等同于 Number([1]) == Number('1')

[1] == true // true
// 等同于 Number([1]) == Number(true)      

上面代碼中,數組[1]與數值進行比較,會先轉成數值,再進行比較;與字元串進行比較,會先轉成數值,然後再與字元串進行比較,這時字元串也會轉成數值;與布爾值進行比較,兩個運算子都會先轉成數值,然後再進行比較。

3、undefined 和 null

undefined和null與其他類型的值比較時,結果都為false,它們互相比較時結果為true。

false == null // false
false == undefined // false

0 == null // false
0 == undefined // false

undefined == null // true      

絕大多數情況下,對象與undefined和null比較,都傳回false。隻有在對象轉為原始值得到undefined時,才會傳回true,這種情況是非常罕見的。

4、相等運算符的缺點

相等運算符隐藏的類型轉換,會帶來一些違反直覺的結果。

0 == ''             // true
0 == '0'            // true

2 == true           // false
2 == false          // false

false == 'false'    // false
false == '0'        // true

false == undefined  // false
false == null       // false
null == undefined   // true

' \t\r\n ' == 0     // true      

上面這些表達式都很容易出錯,是以不要使用相等運算符(==),最好隻使用嚴格相等運算符(===)。

5、不相等運算符

相等運算符有一個對應的“不相等運算符”(!=),兩者的運算結果正好相反。

1 != '1' // false