新手在學(xué)習(xí)JavaScript的運(yùn)算符時(shí)常常碰到一些 == 的問(wèn)題,就是console.log出來(lái)也不懂原因?,F(xiàn)在我就來(lái)解釋一下這部分的知識(shí)點(diǎn)。但需要注意的是,在實(shí)際開發(fā)應(yīng)用中,避免寫出語(yǔ)義不明的code。此文多數(shù)code只是演示,不具備實(shí)際應(yīng)用。
== 是什么
== 是抽象(非嚴(yán)格)相等比較 => Abstract Equality Comparison
對(duì)于的是嚴(yán)格相等比較 => Strict Equality Comparison
嚴(yán)格相等比較是比較兩個(gè)值是否相等,兩個(gè)被比較的值在比較前都不進(jìn)行隱式轉(zhuǎn)換。如果兩個(gè)被比較的值具有不同的類型,這兩個(gè)值是不全等的。否則,如果兩個(gè)被比較的值類型相同,值也相同,并且都不是 number 類型時(shí),兩個(gè)值全等。最后,如果兩個(gè)值都是 number 類型,當(dāng)兩個(gè)都不是 NaN,并且數(shù)值相同,或是兩個(gè)值分別為 +0 和 -0 時(shí),兩個(gè)值被認(rèn)為是全等的。
抽象相等比較是比較兩個(gè)值是否相等,在比較前將兩個(gè)被比較的值轉(zhuǎn)換為相同類型。在轉(zhuǎn)換后(等式的一邊或兩邊都可能被轉(zhuǎn)換),最終的比較方式等同于全等操作符 === 的比較方式。 相等操作符滿足交換律。
用代碼解釋就是
‘1’ == 1 // 左邊的字符串‘1’轉(zhuǎn)換成1,左右數(shù)值相等,所以結(jié)果是true
‘1’ === 1 // String和Number類型不一樣,所以結(jié)果是false
== 在特定的情況下會(huì)產(chǎn)生副作用,在實(shí)際工程中還是采用 ===,避免產(chǎn)生語(yǔ)義不明的代碼。
x == y 的結(jié)果是什么
先來(lái)看看==讓人費(fèi)解的地方
'' == '0'
0 == ''
0 == '0'
false == 'false'
false == '0'
false == undefined
false == null
null == undefined
' \t\r\n ' == 0
是不是覺得很迷惑。下面來(lái)結(jié)合JS的類型轉(zhuǎn)換說(shuō)不定你就能理解了~
== 會(huì)默認(rèn)把兩邊的數(shù)據(jù)類型轉(zhuǎn)換成Number類型然后比較數(shù)值大小。例如:
null == undefined // 特殊 結(jié)果為true 可以使用這個(gè)加上if捕獲變量為null和undefined
Number == String // x == toNumber(y),將字符串轉(zhuǎn)換成數(shù)值
Boolean == any // toNumber(x) == y, 將boolean值轉(zhuǎn)換成數(shù)值
Object == String or Number // toPrimitive(x) == y (觸發(fā)tostring或者valueof方法)
otherwise == otherwise // false
toNumber會(huì)將數(shù)據(jù)轉(zhuǎn)換成什么呢?
Undefined => NaN
Null => 0
Boolean => true ->1, false ->0;
String "abc" -> NaN, "123" -> 123, '' -> 0
toPrimitive
對(duì)于Object類型,先嘗試調(diào)用.valueOf方法獲取結(jié)果,沒有定義就調(diào)用.toString方法。
看懂了嗎,返回去前面讓你費(fèi)解的判斷語(yǔ)句,現(xiàn)在能不能知道原因了呢。
'' == '0' // false 都是字符串,值不相同為false
0 == '' // true '' 轉(zhuǎn)換成Number類型是0,相同為true
0 == '0' // true ‘0’轉(zhuǎn)換成Number類型是0,相同為true
false == 'false' // false 'false'轉(zhuǎn)換成Number類型是NaN,值不相同為false
false == '0' // true false和'0'轉(zhuǎn)換成Number類型都是NaN,值相同為true
false == undefined // false 雖然undefined轉(zhuǎn)換成Number類型是NaN,但是undefined是特殊情況,
false == null // false
null == undefined // true 只存在null == undefined為true這種特殊情況
' \t\r\n ' == 0 // true \t\r\被認(rèn)為空白字符,包含空白字符和/或行結(jié)束符的字符串的數(shù)值是0
!' ' == true //false 先把''轉(zhuǎn)換成boolean值為true,!true就是為false,一個(gè)false一個(gè)true不相等,結(jié)果為false
if(xx)類型轉(zhuǎn)換
if(condition){
//true statement
}else {
//false statement
}
if的小括號(hào)里面最后都會(huì)轉(zhuǎn)化成boolean值
-
沒有抽象相等比較的時(shí)候:
- 當(dāng)空字符串即是 '' 時(shí)為false,空白字符串即 ‘ ’ 為true,其他字符串字符全為true
- 對(duì)象一律為true
- 數(shù)值,只要為+0,=0,NaN,為false,其他數(shù)值為true(注意+’0.00‘最后會(huì)被轉(zhuǎn)化為0,而‘0.00’是字符, 為true
- undefined和null為false
-
有抽象相等比較 == 的時(shí)候
- 按照 x == y得到的結(jié)果的boolean值判斷,true為真,false為假,兩者進(jìn)入的運(yùn)算不一樣。
看看 == 和 === 相同的情況
既然談到 == ,順便也談?wù)?===
var a = [1,2,3];
var b = [1,2,3];
var c = { x: 1, y: 2 };
var d = { x: 1, y: 2 };
var e = "text";
var f = "te" + "xt";
a == b // false
a === b // false
c == d // false
c === d // false
e == f // true
e === f // true
還有當(dāng)將文字與評(píng)估為相同文字的對(duì)象進(jìn)行比較時(shí),會(huì)觸發(fā)其toString或valueOf方法。
例如,考慮將字符串文字與由String構(gòu)造函數(shù)創(chuàng)建的字符串對(duì)象進(jìn)行比較。
“abc”== new String(“abc”)// true
“abc”=== new String(“abc”)// false
這里 == 運(yùn)算符檢查兩個(gè)對(duì)象的值并返回true,但是===看到它們不是相同的類型并返回false。
哪一個(gè)是正確的?這真的取決于你想要比較的東西。
完整比較圖:
紅色:===
橙色:==
黃色:<= 和 >= 同時(shí)成立,== 不成立
藍(lán)色:只有 >=
綠色:只有 <=

最后看看 == 產(chǎn)生的副作用
var x = 1;
var obj = {valueOf: function(){ x = 2; return 0 }}
console.log(obj == 0, x) // true, 2
var x = 1;
var obj = {valueOf: function(){ return {} }, toString: function(){ return {}}}
console.log(obj == 0) // Error: Cannot convert object to primitive value