(譯)js中的神奇的型別轉換

飛翔的大象發表於2019-03-08
  • 此為翻譯文章
  • 原文連結 這篇文章主要講的是運算子中的隱式型別轉換,我只摘了下面的例子

true + false             // 1
12 / "6"                 // 2
"number" + 15 + 3        // 'number153'
15 + 3 + "number"        // '18number'
[1] > null               // true
"foo" + + "bar"          // 'fooNaN'
'true' == true           // false
false == 'false'         // false
null == ''               // false
!!"false" == !!"true"    // true
['x'] == 'x'             // true
[] + null + 1            // 'null1'
[1,2,3] == [1,2,3]       // false
0 || "0" && {}           // {}
{}+[]+{}+[1]             // '0[object Object]1'
!+[]+[]+![]              // 'truefalse'
new Date(0) - 0          // 0
new Date(0) + 0          // 'Thu Jan 01 1970 02:00:00(EET)0'
複製程式碼

true + false

加法運算子會觸發數字轉換

true + false
==> 1 + 0
==> 1
複製程式碼

12 / "6"

除法運算子會觸發字串的數字轉換

"number" + 15 + 3

加法運算子是從左到右結合,所以先執行"number" + 15,因為第一個運算元是字串,加法運算子對15進行字串轉換,第二步也是如此。

15 + 3 + "number"

如同上一個一樣,先執行15+3,因為都是數字,所以不需要進行型別轉換。第二步中,因為一個運算元中有字串,所以對數字進行字串轉換。

[1] > null

比較運算子會觸發對運算元的數字轉換

[1] > null
==> '1' > 0
==> 1 > 0
==> true
複製程式碼

"foo" + + "bar"

右邊運算子比左邊運算子具有更高的優先順序,因此+'bar'表示式先執行。一元加號運算子會觸發對字串進行數字型別轉換,由於字串轉換之後是一個非法的數字,結果是NaN。第二步執行'foo' + NaN

"foo" + + "bar"
==> "foo" + (+"bar")
==> "foo" + NaN
==> "fooNaN"
複製程式碼

'true' == true and false == 'false'

==運算子會觸發數字型別轉換,字串'true'被轉換成NaN,布林true被轉換成1

null == ''

==運算子通常會觸發數字型別轉換,但不是null的情況,null只能和nullundefined進行比較,不能和其他值進行比較。

!!"false" == !!"true"

!!運算子將這兩個字串轉換成布林值true,因為他們不是空的字串, ==不進行型別轉換,只對布林值的true進行比較

['x'] == 'x'

==運算子會觸發對一個陣列進行陣列轉換,陣列的valueOf()方法會返回陣列自己,但是因為陣列不是基本型別,velueOf會被忽略。陣列的toString()僅僅將['x']轉換成字串'x'

[] + null + 1

+會觸發將[]進行數字型別轉換,和上一個一樣進行toString操作,會返回一個空的字串,接下來就進行'' + null + 1

[1,2,3] == [1,2,3]

兩邊有同樣型別,不進行型別轉換,由於==檢查值相等而不是引用相等,兩個陣列是兩個不同的例項,所以結果是false

0 || "0" && {}

邏輯運算子||&&會進行布林型別轉換,但是會返回原始運算元。0false'0'true{}是true,最後返回{}

{}+[]+{}+[1]

所有的運算元都不是基本型別,所以+開始從左邊的觸發數字轉換,陣列和物件的valueOf方法被忽略。使用後備toString方法。這裡有一個訣竅,第一個{}不被看作物件,而是被視為塊宣告語句,因此它被忽略。於是開始從後面的+[]開始進行評估,[]toString返回一個空字串,再對空字串進行數字轉換是0

{}+[]+{}+[1]
==> +[]+{}+[1]
==> 0 + {} + [1]
==> 0 + '[object Object]' + [1]
==> '0[object Object]' + [1]
==> '0[object Object]' + '1'
==> '0[object Object]1'
複製程式碼

!+[]+[]+![]

這個可以根據運算子的優先順序去解釋

!+[]+[]+![]
==> (!+[]) + [] + (![])
==> !0 + [] + false
==> true + [] + false
==> true + '' + false
==> 'truefalse'
複製程式碼

new Date(0) - 0

減號運算子會進行數字轉換。Date.valueOf()返回自Unix紀元以來的毫秒數

new Date(0) - 0
==> 0 - 0
==> 0
複製程式碼

new Date(0) + 0

加號運算子觸發預設轉換。 Date假定字串轉換為預設值,因此使用toString()方法,而不是valueOf()

相關文章