banner
isolcat

isolcat

I am not afraid of storms, for I am learning how to sail my ship
github

一篇文章搞定JavaScript隱式轉換

前言#

由於眾多歷史遺留原因,JavaScript(js)對於類型的掌控沒有那麼強(這也就促成了 TypeScript 的誕生),在日常的開發和刷題時,常常會被 js 的一些「隱式轉換」給折磨得不成人樣,即使是老 js 人有時候都會犯一些錯誤。本文將直接涵蓋 js 的所有隱式轉換情況,讓你一篇文章就能搞定 JavaScript 的隱式轉換。

一張圖查看 js 地獄般的隱式轉換:how-it-fucking-work

1. 減、乘、除#

⭐️當我們對各種非「Number」類型應用數學運算符(- * /)時,會先將非「Number」類型轉換為「Number」類型。

1 - true // 0,首先將 true 轉換為數字 1,然後執行 1 - 1
1 - null // 1,首先將 null 轉換為數字 0,然後執行 1 - 0
1 * undefined // NaN,undefined 轉換為數字是 NaN
2 * ['5'] // 10,['5']首先會變成 '5',然後再變成數字 5

上面例子中的 ['5'] 的轉換,涉及到拆箱操作,將來有機會再出一篇文章說明。

2. 加法的特殊性#

⭐️為什麼加法要區別對待?因為 JavaScript 中的 + 還可以用來拼接字符串。請記住以下 3 條規則:

  • 當一側為「String」類型時,被識別為字符串拼接,並且會優先將另一側轉換為字符串類型。
  • 當一側為「Number」類型,另一側為原始類型時,將原始類型轉換為「Number」類型。
  • 當一側為「Number」類型,另一側為引用類型時,將引用類型和「Number」類型轉換成字符串後拼接。

⭐️以上 3 點,優先級從高到低,即 3+'abc' 會應用規則 1,而 3+true 會應用規則 2。

123 + '123' // 123123(規則1)
123 + null  // 123(規則2)
123 + true // 124(規則2)
123 + {}  // 123[object Object](規則3)

邏輯語句中的類型轉換#

當我們使用 ifwhilefor 等語句時,我們期望表達式是一個「Boolean」值,所以一定伴隨著隱式類型轉換。而這裡面又分為兩種情況:

1. 單個變量#

⭐️如果只有單個變量,會先將變量轉換為布林值。

我們可以參考附錄的轉換表來判斷各種類型轉變為「Boolean」後的值。

不過這裡有個小技巧:

只有「null」、「undefined」、「''」、「NaN」、「0」、「false」這幾個是「false」,其他的情況都是「true」,比如「{}」、「[]」。

2. 使用 == 比較中的 5 條規則#

雖然我們可以嚴格使用 ===,但了解 == 的特性還是很有必要的。

⭐️根據 == 兩側的數據類型,我們總結出 5 條規則:

  • 規則 1:「NaN」和其他任何類型比較永遠返回「false」(包括和它自己)。
NaN == NaN // false
  • 規則 2:布林值和其他任何類型比較時,布林值首先被轉換為數字類型。
true == 1  // true 
true == '2'  // false,先將 true 變成 1,而不是將 '2' 變成 true
true == ['1']  // true,先將 true 變成 1,['1']拆箱成 '1',再參考規則3
true == ['2']  // false,同上
undefined == false // false,首先 false 變成 0,然後參考規則4
null == false // false,同上
  • 規則 3:「String」和「Number」比較時,先將「String」轉換為「Number」類型。
123 == '123' // true,'123' 會先變成 123
'' == 0 // true,'' 會首先變成 0

規則 4:「null == undefined」比較結果是「true」,除此之外,「null」、「undefined」和其他任何結果的比較值都為「false」。

null == undefined // true
null == '' // false
null == 0 // false
null == false // false
undefined == '' // false
undefined == 0 // false
undefined == false // false

規則 5:「原始類型」和「引用類型」做比較時,引用類型會依照「ToPrimitive」規則轉換為原始類型。

⭐️「ToPrimitive」規則是引用類型向原始類型轉變的規則,它遵循先「valueOf」後「toString」的模式,期望得到一個原始類型。

如果仍然無法得到一個原始類型,就會拋出 TypeError

'[object Object]' == {} 
// true,對象和字符串比較,對象通過 toString 得到一個基本類型值
'1,2,3' == [1, 2, 3] 
// true,同上,[1, 2, 3]通過 toString 得到一個基本類型值

通過幾個特別的題目來練習一下吧!

1. [] == ![]

	- 第一步,![] 會變成 false
	- 第二步,應用規則2,題目變成:[] == 0
	- 第三步,應用規則5,[]的valueOf是0,題目變成:0 == 0
	- 所以,答案是 true!

2. [undefined] == false#

	- 第一步,應用規則5,[undefined]通過toString變成'',
	  題目變成 '' == false
	- 第二步,應用規則2,題目變成 '' == 0
	- 第三步,應用規則3,題目變成 0 == 0
	- 所以,答案是 true!
	// 但是 if([undefined]) 又是個true!

3. 更多的題目#

更多的練習,大家去生活中去發現吧。(悲慘的生活)

⭐️強烈建議大家去找各種奇奇怪怪的題目,反復練習上面 5 條規則,直到熟練於心。

附錄 1:類型轉換表#

這個表格非常實用,在執行上面提到的轉換規則時,可以參考這個對照表。

convert-table

載入中......
此文章數據所有權由區塊鏈加密技術和智能合約保障僅歸創作者所有。