Karen Huang
7 min readOct 23, 2021

ㄟ問你喔,強制轉型是什麼?轉換型別有規則可循嗎?(數字型別篇)

Photo by Nick Hillier on Unsplash

繼強制轉型的布林值、字串篇之後,本篇獨立出來,將主要在歸納強制轉型在數字型別這一部分的重點,並找出隱性轉型背後的原理。

數字的顯性與隱性轉型

數字的顯性轉型

數字的顯性轉型一樣是透過函式,這邊將透過 Number() 為例說明,而根據印出的結果觀察到:

  • 透過 Number() 能轉為數字的,就會回傳數字
  • 透過 Number() 無法轉為數字的,會轉出 NaN(像是 undefined )
  • 在運算過程當中,布林值 true 被 Number() 轉為數字 1、false 為數字 0
  • null、空字串將會被 Number() 轉為 數字 0
let a = '666666'; 
let b = 'seven'
let c = true;
let d = false;
let e = null;
let f = undefined;
let g = "";
console.log(Number(a), typeof Number(a)); // 回傳 666666 'number' console.log(Number(b), typeof Number(b)); // 回傳 NaN 'number'
console.log(Number(c), typeof Number(c)); // 回傳 1 'number'
console.log(Number(d), typeof Number(d)); // 回傳 0 'number'
console.log(Number(e), typeof Number(e)); // 回傳 0 'number'
console.log(Number(f), typeof Number(f)); // 回傳 NaN 'number'
console.log(Number(g), typeof Number(g)); // 回傳 0 'number'

註:parseInt() 能將數字的字串取整數。

數字的隱性轉型

有運算子的時候,隱性轉型將自動把值轉換為數字型別進行運算,若無法轉為數字型別的,則會轉為字串。

Part 1: 算術運算子

1. 算術運算子:加法( + )

let a = 3 + true //4 'number' 
let b = true + false //1 'number'
let c = null + true; //1 'number'
let d = null + 666; //666 'number'
let e = undefined + 3; //NaN 'number'
無法轉換為數字的 undefined:
console.log(undefined + null) // 回傳 NaN (number)

註:當 ( + ) 遇到字串就不會轉為數字型別!

2. 算術運算子:減法( - )

let a = 3 - true //2 'number' 
let b = true - false //1 'number'
let c = null - true; //-1 'number'
let d = null - 666; //-666 'number'
let e = undefined - 3; //NaN 'number'

3 & 4. 算術運算子:乘法( * )、除法( / )

let a = 3 * "6"; // 18 'number' 
let b = true * "3";// 3 'number'
let c = undefined * 3; // NaN 'number'
let d = undefined * "3"; // NaN 'number'
let e = undefined * true; // NaN 'number'
let f = null * 666; // 0 'number'
let g = null * "666"; // 0 'number'
let h = null * true; // 0 'number'

註1:字串遇到乘法、除法都會轉為數字型別
註2:任何值與 undefined 相乘、相除都是 NaN
註3:任何值與 null 相乘、相除都是 0

Part 2: 比較運算子

在算術運算子整理到一段落後,接著是探討比較運算子 == 和 != 在強制轉型中的背後原理。

為什麼是這兩個呢?

因為首先需要知道:

比較運算子的 == 和 != 著重在「值」的比較,不去比較型別,可允許強制轉型發生作用。

但 === 及 !== 則不允許強制轉型的發生,因此,當你不希望程式碼的運算過程中被 JS 強制轉型,請記得要使用 ===或 !==。

四種比較運算子的簡表

比較運算子:==

範例1 
console.log(666 == '666'); // true
console.log(666 === '666'); // false

在範例 1 中,== 的運算過程,為了要比較「值」,會執行隱性轉型的動作,可以視為是字串 ‘666’ 被隱性轉型為 Number(‘666’),故得到運算結果為 true。

而 === 會先比較型別、再比較「值」,因此 === 只要先發現型別不同,就回傳 false,所以這也是當不希望程式碼被 JS 隱性轉型的時候,就應該使用 === 的原因。

再看下一個例子:

範例 2 中,true 跟 ‘1’ 都經歷了隱性轉型的過程,第一行程式碼可以視為是 Number(true) == Number(‘1’),故得到 true。

範例2
console.log(true == '1'); //true
console.log(true === '1'); //false

再看最後一個例子:

由於上述兩個範例都是能被轉換為數字型別的,但是,當遇到非字串也非布林值的狀況,結果會是如何?

範例3
console.log(null == ''); //false
console.log(null === ''); //false

這邊在==的運算中,可以視 null 為 String(null),所以是 ‘null’ 不等於空字串,故得到 false。原因是隱性轉型是由 JS 來幫你決定轉哪一種,

運算子的運算過程中,會先自動轉為數字型別,若不能轉為數字的,會改而轉字串,再比較值

比較運算子:!=

範例1 
console.log(666 != '666'); // false
console.log(666 !== '666'); // true
範例2
console.log(true != '1'); // false
console.log(true !== '1'); // true

到底為什麼,範例 1 的666 不等於 ‘666’ 是 true,但 666 不等於 ‘666’ 又變成 false?

很關鍵的一點就在於,比較運算子 != 也是會忽略型別,並允許字串被轉換為數字,再比較「值」;相反地,!== 則是會優先比較型別,再看值。

而在範例 2 中,遇到兩者都非數字的情況下,運算過程也可被視為是 Number(true) 跟 Number(‘1’) 的運算,故得到 false 的結果。

總結

最後歸納出四個重點:

  1. 強制轉型有分為顯性轉型與隱性轉型,不管哪一種轉型,也只會轉出布林值、字串或數字其中一種。
  2. 顯性轉型都是以人為、用函式的方法將值轉換為自己指定要的型別。
  3. 隱性轉型是由 JS 來幫你決定轉哪一種,當有運算子的時候,會優先轉為數字型別;遇到無法轉為數字的,改而轉成字串,再比較值。
  4. 承第 3 點,加法運算子是較為特殊的一種,若遇到有字串,則優先轉字串再比較值。

參考資料

  1. MDN — Equality comparisons and sameness
  2. MDN — 算術運算子
  3. 重新認識 JavaScript: Day 07 「比較」與自動轉型的規則
  4. 何謂強制轉型、以及如何作到轉換型別?
  5. Type Coercion in JavaScript
  6. Day11 — 寬鬆相等 VS. 嚴格相等
  7. [27] 強制轉型 — 寬鬆相等 ( == ) vs. 嚴格相等 ( === )
  8. [27–1] 強制轉型 — 番外篇 ( 運算子預設的規定 ex: ==、+ )
Karen Huang
Karen Huang

Written by Karen Huang

寫下來的,比較不容易忘記。

No responses yet