譯者按: JavaScript有不少坑,常常一不當心就要寫bug。javascript
爲了保證可讀性,本文采用意譯而非直譯。另外,本文版權歸原做者全部,翻譯僅用於學習。html
JavaScript是一門偉大的語言,它擁有很是簡潔的語法,龐大的生態系統,以及最重要的:有一個偉大的社區支撐着。同時,咱們也知道JavaScript是一個充滿技巧性的語言。有些坑足以讓咱們崩潰,也有些奇淫技巧讓咱們以爲頗有趣。本文的思想源自於Brian Leroux在dotJS2012上的演講「WTFJS」 at dotJS 2012。前端
<div style="text-align: center;">
<img style="width:80%;" src="javascript-werid-series-1/brian.jpeg" />
</div>java
我收集這些例子的主要目的是將它們整理並清楚理解它們的原理。從中學到不少之前不懂的知識是一件頗有趣的事情。若是你是初學者,你能夠經過學習這些筆記深刻理解JavaScript;若是你是一個專業的開發者,那麼能夠將這些筆記做爲一個不錯的引用資料。無論怎樣,只要讀下去,你就會學到新東西的。git
[ ] == ![ ] // -> true
相等(==)判斷操做會將兩邊的類型都轉換爲數字(number),而後再比較。由於[]
和![]
都會轉換爲0
。咱們能夠理解[]
是一個數組,只不過爲空而已,那麼爲true。右側![]
則爲false。false而後轉換爲數字0。左側[]
直接轉換爲數字,由於空數組會轉換爲0
,因此儘管咱們認爲[]
爲true,這裏卻變成了0
。github
下面是簡化的計算過程:算法
+[] == +![] 0 == +false 0 == 0 true
參考:數組
!!'false' == !!'true' // -> true !!'false' === !!'true' // -> true
true是一個真值,用1表示;字符串的「true」
則爲NaN。瀏覽器
true == 'true' // -> false false == 'false' // -> false
'false'是一個有意義的字符串。less
!!'false' // -> true !!'true' // -> true
參考:7.2.13 Abstract Equality Comparison
'b' + 'a' + + 'a' + 'a' // -> baNaNa
這是一箇舊笑話,不過改進過的。原始的長這樣:
'foo' + + 'bar' // -> 'fooNaN'
該表達式以'foo' + (+'bar')
的形式計算,由於bar
不是數字,因此轉換爲NaN。
參考:
NaN === NaN // -> false
根據===
的算法,咱們能夠容易理解爲何爲false。
若是typeof(x)和typeof(y)不一樣,那麼返回false.
不然,若是typeof(x)是Number,那麼
- 若是x是NaN,那麼返回false;
- 若是y是NaN,那麼返回false;
- ...
由此能夠得出值爲false的結論。
(![]+[])[+[]]+(![]+[])[+!+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]] // -> fail
若是咱們仔細觀察序列的規律,會發現下面的模式出現不少次:
(![]+[]) // -> 'false' ![] // -> false
所以,咱們嘗試將[]和false相加。可是根據內部一些列函數的計算(binary + Operator -> ToPrimitive -> [[DefaultValue]]),右側的[]最終轉換爲string:
(![]+[].toString()) // 'false'
對於一個字符串,咱們就能夠經過下標來獲取對應的字符:
'false'[0] // -> 'f'
剩下的都很直觀,除了i
很取巧。fail
中的i
是經過在falseundefined
中獲取第十個下標對應的字符而獲得。
空數組不等於true。(An array is a truthy value, however, it's not equal to true.)
!![] // -> true [] == true // -> false
參考:
儘管null是一個false的值,可是null不等於false。
!!null // -> false null == false // -> false
不過,若是和其它false的值比較,那麼他們又是相等的。
0 == false // -> true '' == false // -> true
參考: 7.2.13 Abstract Equality Comparison
JavaScript坑不少,趕忙使用fundebug扶一扶!
⚠️這個是前端瀏覽器API,在Nodejs環境沒法使用。
儘管document.all能夠返回一個像數組同樣的對象,能夠用來訪問DOM節點。可是呢,經過typeof查看document.all,你會驚訝地發現類型是undefined
。
document.all instanceof Object // -> true typeof document.all // -> 'undefined'
並且,document.all並不等於undefined。
document.all === undefined // -> false document.all === null // -> false
並且,更驚訝的是:
document.all == null // -> true
document.all是一個過去經常使用的獲取DOM元素的方法,特別是老版本的IE。可是從未進入標準,儘管普遍使用在過去的JS代碼中。當新的API突出來(好比document.getElementById)後,document.all就被淘汰了。標準委員會不得不以爲怎麼處理它。但是由於它已經被普遍使用,因此委員會以爲保留它,可是違背了JavaScript的規範。
參考:
Number.MIN_VALUE
是最小的數,可是它比0還大。
Number.MIN_VALUE > 0 // -> true
由於Number.MIN_VALUE
是5e-324
。也就是說即便最小的值也能夠用浮點數表示出來,雖然離0很接近,可是依然比0大。其實最小的數是Number.NEGATIVE_INFINITY
,儘管它不是一個實際存在的數。
在StackOverflow有相關問題:Why is 0 less than Number.MIN_VALUE in JavaScript?。