[譯] 我見過最好最詳細的 JavaScript 關係的解釋

banner

TLDR:強迫本身使用三重等號(===)

我無心在Reddit上找到了這個JavaScript meme,它是我見過最好的抽象。javascript

tldr

你能夠經過運行開發者工具來運行(圖中)的每行代碼來驗證此關係的準確性。結果並不使人驚訝,但仍然使人失望。java

固然,這個小實驗觸發了個人興趣...git

這是怎麼發生的?

why-does-this-happen

憑藉經驗,我學會了接受JavaScript這滑稽的一面,同時感覺它的鬆散。儘管如此,這個事件的細節仍然讓我感到困惑。github

正如Kyle Simpson所說...算法

"無論怎麼說,我認爲任何人都不會真正瞭解JS"編程

當這些案例出現時,最好查閱源代碼--構建JavaScript的官方ECMAScript規範數組

有了這個規範,讓咱們深入理解這裏發生了什麼。app

板塊1 - 引入強制

panel-1-1

若是你在開發者控制檯上運行0 == "0",爲何它返回true編程語言

0是一個數字,而後"0"是一個字符串,它們永遠不該該相同的!大多數編程語言都遵照它。例如,Java中的0 == "0",會返回下面這個:工具

error: incomparable types: int and String
複製代碼

這頗有道理。若是要比較Java中的intString,必須先把它們轉換爲相同的類型。

但這是JavaScript,大家呀!

this-is-javascript

當你經過==比較兩個值時,其中一個值可能受到強制轉換。

強制 - 自動將值從一種類型轉換爲另外一種類型。

這裏的自動是關鍵詞。JavaScript不是在顯式轉換你的類型,而是在幕後幫你完成。

scumbag-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....
複製代碼

that-string-secretly-became-a-number

奇怪吧?好好習慣它,咱們接着說~

板塊2 - 數組也被強制

panel-2

這種強制不只僅限制於字符串,數字或布爾值等基本數據類型。這是咱們的下一個比較:

0 == [] // true
// What happened...?
複製代碼

再次被強制了!我將解釋規範的相關部分:

If x is String or Number and y is Object, return x == ToPrimitive(y)

譯:若是 x 是字符串或數字類型,而後 y 是對象類型,將 y 轉換爲基本數據類型與 x 做比較後返回

這裏有三件事:

1.是的,數組是對象

arrays-are-objects

抱歉,刷新了你的認知。

2.空數組變成空字符串

再次根據規範,JS首先尋找一個對象的toString方法來強制轉換它。

在數組的狀況下,toString鏈接其全部元素並將它們做爲字符串返回。

[1, 2, 3].toString() // "1,2,3"
['hello', 'world'].toString() // "hello,world"
複製代碼

由於咱們的數組是空的,咱們沒內容去拼接!因此...

[].toString() // ""
複製代碼

empty-array-coerces-to-empty-string-1

規範中的ToPrimitive將空數組轉換成空字符串。相關的參考在這裏這裏,方便你查閱(或解決疑惑)。

3.空字符串而後變成0

empty-strings-become-0

你不能把這些東西搞定。如今咱們已經將數組強制變成"",咱們又回到了第一個算法(規範)...

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...

coercion-every-time-2

板塊3 - 快速回顧

panel-3-1

這是正確的

0 == "0" // true
複製代碼

由於被強制轉換成這個0 == ToNumber("0")

這也是正確的

0 == [] // true
複製代碼

由於強制轉換執行兩次:

  1. ToPrimitive([])轉換爲空字符串
  2. 而後ToNumber("")轉換爲 0 。

因此,告訴我...根據上面的規則,下面將返回什麼?

"0" == []
複製代碼

板塊4 - FALSE!

panel-4-1

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的緣由。

總結

just-use-triple-equals

使用三重等號(===),而後晚上睡個好覺。

0 === "0" // false
0 === [] // false
"0" === [] // false
複製代碼

它徹底避免強制轉換,因此我猜它也更有效率!

可是('==='對於)性能的提高几乎毫無心義。真正的勝利是你在代碼中增長的信心,使得額外的擊打鍵盤徹底值得。

參考和後話

更多的內容,請戳個人博客進行了解,能留個star就更好了💨

相關文章
相關標籤/搜索