JavaScript 什麼是強制轉型(type coercion)、以及如何轉型?
強制轉型是在轉什麼?
「轉型」就是將資料型別轉換成另一種資料型別。
JavaScript 資料型別
- 基本型別 Primitive
- Boolean
- Null
- Undefined
- Number
- String
- Symbol
- 物件型別
- Object
- Array
轉型的規則
以下的表格為輸入的資料型別及轉型後的結果:
ToBoolean
輸入的資料型別 | 轉為 Boolean 的結果 |
---|---|
Undefined | 回傳 false |
Null | 回傳 false |
Boolean | 輸入什麼就回傳什麼 |
Number | 如果是+0 -0 或 NaN 就回傳 false ,否則就回傳 true |
String | 如果是空字串就回傳 false (因為字串長度為 0),否則回傳 true |
Symbol | 回傳 true |
Object | 回傳 true |
ToNumber
輸入的資料型別 | 轉為 Number 的結果 |
---|---|
Undefined | 回傳 NaN |
Null | 回傳 0 |
Boolean | 如果是 true 就回傳 1 ,如果是 false 就回傳 0 |
Number | 輸入什麼就回傳什麼 |
String | 如果可以轉數字就回傳 轉數字後的資料 ,否則回傳 NaN |
Symbol | 拋出 TypeError |
Object | 執行下列步驟來產生回傳值 1. 用 valueOf() 取得基本型別值,接著用 toString() 轉為字串 2. 把轉字串的值再轉數字,回傳 轉型後的值 |
ToString
輸入的資料型別 | 轉為 String 的結果 |
---|---|
Undefined | 回傳 'undefined' |
Null | 回傳 'null' |
Boolean | 如果是 true 就回傳 'true' 如果是 false 就回傳 'false' |
Number | 1. 如果是 NaN 就回傳 'NaN' 2. 如果是 +0 或 -0 就回傳 '0' 3. 如果是 小於零 就回傳 負數字串 。例如:-100 轉型後為'-100' 4. 如果是 無限大 就回傳 'Infinity' 點我看更多 |
String | 輸入什麼就回傳什麼 |
Symbol | 拋出 TypeError |
Object | 執行下列步驟來產生回傳值 1. 用 toString() 轉為字串,如果無法轉字串就用valueOf() ,再將結果toString() 轉型 2. 回傳 轉型後的值 |
💡 詳細規則請點此看文件,不過我想大部分的人應該不會看…
發生「強制轉型」的情境
- 使用 JavaScript 的方法,把變數轉換為另一個型別。
- 把不同資料型別的變數拿來做運算,JavaScript 會
很貼心的把變數轉換為同一個型別,才進行運算。
💡 使用 JavaScript 方法來轉型,稱為「顯式轉型」(explicit type coercion);
💡 JavaScript 幫你轉,稱為「隱式轉型」(implicit type coercion)
顯式轉型 explicit type coercion (使用 JavaScript 方法來轉型)
如果我們希望把現在的資料型別,轉換成另一種資料型別,就可用 JavaScript 提供的方法來「手動」轉換。
String
使用 String()
來把數字轉字串。
- 可以把數字、值、變數,甚至是表達式轉成字串。
💡 把表達式轉字串的執行順序是先算完再轉型,所以把表達式轉型會得到運算結果的字串。
1 | let x = 5 // x 原本是數字 |
另外,用 toString()
的結果也是一樣。
1 | let x = 5 // x 原本是數字 |
其他資料型別
1 | String(null) // 'null' |
Number
使用 Number()
來把字串轉數字。
- 如果是數字的字串,會轉為數字
- 如果是空字串,會轉為0
- 如果不是上面兩種,就會轉為NaN
1 | Number('123') // 123 |
其他資料型別
1 | Number(null) // 0 |
Boolean
用 Boolean()
轉型為布林值
- 只要不是 falsy,都回傳
true
1 | // falsy values |
用 Number()
來把布林值轉為數字
1 | Number(true) // 1 |
用 String()
來把布林值轉為字串
1 | String(true) // 'true' |
Date
把 Date 物件轉型
- 轉成數字會得到 timestamp
- 轉成文字會得到 ISO 8601 格式的字串
- 轉成布林值會得到
true
1 | let d = new Date() |
隱式轉型 implicit type coercion (JavaScript 幫你轉型)
如果把兩個不同資料型別的變數進行運算,JavaScript 會避免發生錯誤而自動把型別進行轉換,確保程式可以繼續執行,但對開發者來說,JavaScript 的貼心很容易造成預期外的結果。
自動轉型成 String 的時機
字串跟其他資料型別做+
的運算,會把另一個資料型別轉為字串,回傳結果為字串。
💡 會與 String.concat() 的結果一樣
1 | '2' + 345 // '2345' |
自動轉型成 Number 的時機
使用算術運算子 +
、-
、*
、/
、%
來做運算,會把「符號前後」的資料都轉型為數字來做運算,回傳的結果為數字。
⚠ 如果+
前後的值有一個是字串,則都轉為字串做運算,回傳結果為字串。
1 | // 轉為數字 |
使用比較運算子 >
、<
、>=
、<=
、==
、!=
來做運算,會把「符號前後」的資料都轉型為數字來做運算,回傳的結果為布林值。
⚠ 如果==
或 !=
前後的值都是字串,運算時不會轉成數字。
⚠ 如果==
前後的值是 null
或 undefined
,運算時不會轉成數字。
1 |
|
自動轉型成 Boolean 的時機
使用邏輯運算子(||
、&&
、!
)來做運算,會把「符號前後」的資料都轉型為真值 truthy 或假值 falsy 來做運算,回傳的結果為布林值。
試試看
💪 試著解釋下列結果為何? 符號前後轉型為何?
1 | '2' / 345 |
參考資料
JavaScript type coercion explained
ECMAScript 2015 Language Specification – ECMA-262 6th Edition
Expressions and operators - JavaScript | MDN
你懂 JavaScript 嗎?#8 強制轉型(Coercion) | Summer。桑莫。夏天