我無心在Reddit
上找到了這個JavaScript meme
,它是我見過最好的抽象。javascript
你能夠經過運行開發者工具來運行(圖中)的每行代碼來驗證此關係的準確性。結果並不使人驚訝,但仍然使人失望。java
固然,這個小實驗觸發了個人興趣...git
憑藉經驗,我學會了接受JavaScript
這滑稽的一面,同時感覺它的鬆散。儘管如此,這個事件的細節仍然讓我感到困惑。github
正如Kyle Simpson
所說...算法
"無論怎麼說,我認爲任何人都不會真正瞭解JS"編程
當這些案例出現時,最好查閱源代碼--構建JavaScript的官方ECMAScript規範。數組
有了這個規範,讓咱們深入理解這裏發生了什麼。app
若是你在開發者控制檯上運行0 == "0"
,爲何它返回true
?編程語言
0
是一個數字,而後"0"
是一個字符串,它們永遠不該該相同的!大多數編程語言都遵照它。例如,Java
中的0 == "0"
,會返回下面這個:工具
error: incomparable types: int and String
複製代碼
這頗有道理。若是要比較Java
中的int
和String
,必須先把它們轉換爲相同的類型。
但這是JavaScript
,大家呀!
當你經過==
比較兩個值時,其中一個值可能受到強制轉換。
強制 - 自動將值從一種類型轉換爲另外一種類型。
這裏的自動是關鍵詞。JavaScript
不是在顯式轉換你的類型,而是在幕後幫你完成。
若是你有目的地利用它,這很方便,但若是你不知道它的含義,則可能有害。
這是關於它的官方ECMAScript語言規範。 我會解釋相關部分:
If x is Number and y is String, return x == ToNumber(y)
譯:若是 x 是數字類型,y 是字符串類型,將 y 轉換成數字類型與 x 做比較後返回
因此咱們的例子0 == "0"
:
由於 0 是一個數字類型,"0" 是一個字符串類型,則返回 0 == ToNumber("0")
咱們的字符串"0"
已經被祕密轉換成數字0
,如今咱們有一個匹配了!
0 == "0" // true
// The second 0 became a number!
// so 0 equals 0 is true....
複製代碼
奇怪吧?好好習慣它,咱們接着說~
這種強制不只僅限制於字符串,數字或布爾值等基本數據類型。這是咱們的下一個比較:
0 == [] // true
// What happened...?
複製代碼
再次被強制了!我將解釋規範的相關部分:
If x is String or Number and y is Object, return x == ToPrimitive(y)
譯:若是 x 是字符串或數字類型,而後 y 是對象類型,將 y 轉換爲基本數據類型與 x 做比較後返回
這裏有三件事:
抱歉,刷新了你的認知。
再次根據規範,JS首先尋找一個對象的toString
方法來強制轉換它。
在數組的狀況下,toString
鏈接其全部元素並將它們做爲字符串返回。
[1, 2, 3].toString() // "1,2,3"
['hello', 'world'].toString() // "hello,world"
複製代碼
由於咱們的數組是空的,咱們沒內容去拼接!因此...
[].toString() // ""
複製代碼
規範中的ToPrimitive
將空數組轉換成空字符串。相關的參考在這裏和這裏,方便你查閱(或解決疑惑)。
你不能把這些東西搞定。如今咱們已經將數組強制變成""
,咱們又回到了第一個算法(規範)...
If x is Number and y is String, return x == ToNumber(y)
因此0==""
Since 0 is Number and "" is String, return 0 == ToNumber("")
ToNumber("")
返回 0 。
所以,再一次是0==0
...
0 == "0" // true
複製代碼
由於被強制轉換成這個0 == ToNumber("0")
。
0 == [] // true
複製代碼
由於強制轉換執行兩次:
ToPrimitive([])
轉換爲空字符串ToNumber("")
轉換爲 0 。因此,告訴我...根據上面的規則,下面將返回什麼?
"0" == []
複製代碼
FALSE! 正確。
若是你明白規則,這部分是有意義的。
下面是咱們的比較:
"0" == [] // false
複製代碼
再次參考規範:
If x is String or Number and y is Object, return x == ToPrimitive(y)
那就意味着...
Since "0" is String and [] is Object, return x == ToPrimitive([])
"0" == ""
複製代碼
"0"
和""
都是字符串類型,因此JavaScript
不須要再強制轉換了。這就是爲何獲得結果爲false
的緣由。
使用三重等號(===),而後晚上睡個好覺。
0 === "0" // false
0 === [] // false
"0" === [] // false
複製代碼
它徹底避免強制轉換,因此我猜它也更有效率!
可是('==='對於)性能的提高几乎毫無心義。真正的勝利是你在代碼中增長的信心,使得額外的擊打鍵盤徹底值得。
更多的內容,請戳個人博客進行了解,能留個star就更好了💨