先來公佈答案:console.log([] == ![]) // true
,是不是很酷。==
還有個好兄弟——===
,下面就來看看哥倆到底幹了啥...
==
的執行機制
==運算子為確定兩個運算數是否相等,會對左右兩邊運算數進行型別轉換。
執行型別轉換的規則
- 如果一個運算數是Boolean值,在檢查相等性之前,把它轉化成數字值。false轉化成0,true轉換為1。
- 如果一個運算數是字串,另一個是數字,在檢查相等性之前,要嘗試把字串轉換成數字。
- 如果一個運算數是物件,另一個是字串,在檢查相等性之前,要嘗試把物件轉換成字串。
- 如果一個運算數是物件,另一個是數字,在檢查相等性之前,要嘗試把物件轉換成數字。
遵守規則
- 值null和undefined相等。
- 在檢查相等性時,不能把null和undefined轉換成其他值。
- 如果某個運算數是NaN,等號將返回false,非等號將返回true。
- 如果兩個運算都是物件,那麼比較它們的引用值。如果兩個運算數指向同一個物件,那麼符號返回true,否則兩個運算數不等。
===
的執行機制
- 如果型別不同,就[不相等]
- 如果兩個都是數值,並且是同一個值,那麼[相等];例外的是,如果其中至少一個是NaN,那麼[不相等]。(判斷一個值是否是NaN,只能用isNaN()來判斷)
- 如果兩個都是字串,每個位置的字元都一樣,那麼[相等];否則[不相等]。
- 如果兩個值都是true,或者都是false,那麼[相等]。
- 如果兩個值都引用同一個物件或函式,那麼[相等];否則[不相等]。
- 如果兩個值都是null,或者都是undefined,那麼[相等]。
回頭來驗證一下[] == ![]
。
第一步:根據運算子的優先順序,!
先執行,[]
是一個物件,所以![]
轉化為false
第二步:根據型別轉換規則第一條——"如果一個運算數是Boolean值,在檢查相等性之前,把它轉化成數字值。false轉化成0,true轉換為1。"。所以false
轉換成0
(==
右邊得到0
)
第三步:根據型別轉換規則第三條——"如果一個運算數是物件,另一個是字串,在檢查相等性之前,要嘗試把物件轉換成字串。"。左邊的[]
呼叫toString()
,轉換成空字串''
第四步:根據型別轉換規則第二條——"如果一個運算數是字串,另一個是數字,在檢查相等性之前,要嘗試把字串轉換成數字。"。''
轉化成0
。(左邊得到0
)
第五步:比較兩邊大小0==0
,因此結果為true
總結
轉化規則那麼多,鬼能記得住啊,總結一下,分兩類去記就好:
- 原始型別(undefined、null、number、boolean、string)的比較。轉成數字的優先順序最高,也就是說一方出現數字,另一方也要轉成數字比較。
- 原始型別和物件(引用)型別的比較。如果一個是物件,另一個是數值或字串,把物件轉換成基礎(原始)型別的值再比較。物件轉換成基礎型別,利用它的object.toString()或者object.valueOf()方法。
補充一點:雖然==
和===
是比較運算子,但它只是結果返回Boolean值,轉化到最後比較的一定不是倆個Boolean值。