先來公佈答案:console.log([] == ![]) // true
,是否是很酷。==
還有個好兄弟——===
,下面就來看看哥倆到底幹了啥...函數
==
的運行機制
==運算符爲肯定兩個運算數是否相等,會對左右兩邊運算數進行類型轉換。code
執行類型轉換的規則
- 若是一個運算數是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值。string