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: ==、+ )

Sign up to discover human stories that deepen your understanding of the world.

Free

Distraction-free reading. No ads.

Organize your knowledge with lists and highlights.

Tell your story. Find your audience.

Membership

Read member-only stories

Support writers you read most

Earn money for your writing

Listen to audio narrations

Read offline with the Medium app

Karen Huang
Karen Huang

Written by Karen Huang

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

No responses yet

Write a response