### 🔍小範例大學問👊 # [<font color="#f00">JavaScript</font>] 何謂強制轉型、以及如何作到轉換型別? --- ## 1. 強制轉型的種類: * 「明確的」強制轉型(explicit coercion): 程式碼中刻意寫出來的型別轉換。 * 「隱含的」強制轉型(implicit coercion): 程式碼中沒有明確指出要轉換型別卻轉型了。 ## 2. 「明確的」強制轉型(explicit coercion): #### 🔄強制轉型成字串 String() ```javascript= let a = 1; let b = String(a); console.log(typeof a); // number console.log(typeof b); // string ``` ```javascript= let c = null; let d = String(c); console.log(typeof d, d); // string null let e = undefined; let f = String(e); console.log(typeof f, f); // string undefined let g = true; let h = String(g); console.log(typeof h, h); // string true let i = [1, 2, 3]; let j = String(i); console.log(typeof j, j); // string "1,2,3" let n = { myName: "Peter", age: 18 }; let m = String(n); console.log(typeof m, m); // string [object Object] ``` 💬說明:物件轉型字串時,不管物件內容為何,強制轉型後都會形成 [object Object] 。 #### 🔄強制轉型成數字 number() ```javascript= let a = '1'; let b = Number(a); console.log(typeof b, b); // number 1 ``` ```javascript= let a = '我是誰'; let b = Number(a); console.log(typeof b, b); // number NaN let c = [1, 2, 3]; let d = Number(c); console.log(typeof d, d); // number NaN let e = { age : 18, myName :'Peter' }; let f = Number(e); console.log(typeof f, f); // number NaN ``` 💬說明:如果轉型字串非數字時,強制轉型後會形成 NaN 。 ```javascript= let a = null; let b = Number(a); console.log(typeof b, b); // number 0 let c = undefined; let d = Number(c); console.log(typeof d, d); // number NaN let e = true; let f = Number(e); console.log(typeof f, f); // number 1 ``` 💬說明: true 的值為 1 ; false 的值為 0 。 #### 🔄強制轉型成布林值 number() ```javascript= let a = ''; let b = Boolean(a); console.log(typeof b, b); // boolean false let c = NaN; let d = Boolean(c); console.log(typeof d, d); // boolean false let e = 0; let f =Boolean(e); console.log(typeof f, f); // boolean false let g = null; let h =Boolean(g); console.log(typeof h, h); // boolean false let i = undefined; let j =Boolean(i); console.log(typeof j, j); // boolean false let m = false; let n =Boolean(m); console.log(typeof n, n); // boolean false ``` 💬說明:除了上述六種情況都會強制轉型為 boolean 的 false 之外,都會轉型成 boolean 的 true。 | ( 六種 | 強制轉型 | false ) | | | | |:-----:|:--------:|:-----:|:----:|:---:|:---------:| | false | 空字串 | 0 | null | NaN | undefined | ## 3. 「隱含的」強制轉型(implicit coercion): #### 🔄強制轉型成字串 string ( +加法 ) ```javascript= const a = '2'; const b = 3; const c = true; const d = null; const e = undefined; const f = NaN; const g = [4, 5]; const h = { A:1, B:2 } console.log(a + b); // 23 console.log(a + c); // 2true console.log(a + d); // 2null console.log(a + e); // 2undefined console.log(a + f); // 2NaN console.log(a + g); // 24,5 console.log(a + h); // 2[object Object] ``` 💬說明:字串跟所有型別做加法時,皆會強制轉型為字串。 ```javascript= console.log(typeof (b + c)); // number console.log(typeof (b + d)); // number console.log(typeof (b + e)); // number console.log(typeof (b + f)); // number console.log(typeof (b + g)); // string console.log(typeof (b + h)); // string ``` 💬說明:除了數字型別之外的加法,皆會強制轉型為字串。 | ( + 法 | 視為 | 數字型別 ) | | | |:------:|:-------:|:----------:|:----:|:---------:| | number | boolean | NaN | null | undefined | #### 🔄強制轉型成數字 number ( -減 *乘 /除法 ) ```javascript= console.log(typeof (b - a)); // number console.log(typeof (b * a)); // number console.log(typeof (b / c)); // number console.log(typeof (b - c)); // number console.log(typeof (b * d)); // number console.log(typeof (b / d)); // number console.log(typeof (b * e)); // number console.log(typeof (b / e)); // number console.log(typeof (b * f)); // number console.log(typeof (b / f)); // number ``` 💬說明:毫無懸念,全數為數字型別(但不是所有都是強制轉型,可參考上面的那張表格)。 * <font color="#f00">來看一下陣列和物件做減、乘、除法,會如何?</font> ```javascript= console.log(typeof (g - h), g - h); // number NaN console.log(typeof (g * h), g * h); // number NaN console.log(typeof (g / h), g / h); // number NaN ``` 💬說明:沒想到,還是強制轉型為數字型別(竟然不會報錯!)。 #### 🔄強制轉型成布林值 boolean 在什麼狀況下會隱含地將值強制轉為布林呢?直接看實例吧。 ```javascript= let a = 520; let b = '森七七也是真的'; let c = undefined; let d = null; if (a) { // true console.log(`${a}是真的`); // 520是真的 } while (c) { // false console.log('我想~不告訴你'); // 因為是false,所以不會出現 } let tellMe = (c == d) ? b : a; //true console.log(tellMe); // 森七七也是真的 if (a || b) { // true console.log('你搞的我好亂啊'); // 你搞的我好亂啊 } ``` | ( 強制轉型布林 ) | |:---------------------------------- | | if => 條件判斷 | | for => 的條件判斷 | | while => 條件是否成立 | | 三元運算式 => 值1 : 值2 的條件運算 | | 邏輯運算子 => OR 、 AND | ## 4. Symbol 的強制轉型: ```javascript= const a = Symbol('強制轉字串很可以'); String(a); console.log(a);// "Symbol(強制轉字串很可以)" const b = Symbol('轉字串來暗的不行喔'); b + ''; // TypeError: Cannot convert a Symbol value to a string(錯誤訊息) ``` 💬說明:在轉為字串方面,將 symbol 明確的強制轉型是允許的,但隱含的強制轉型是被禁止的,並且會丟出錯誤訊息。 ```javascript= const c = Symbol(123); Number(c); // TypeError: Cannot convert a Symbol value to a number(錯誤訊息) const d = Symbol(456); 789 + d; // TypeError: Cannot convert a Symbol value to a number(錯誤訊息) ``` 💬說明:在轉為數字方面,無論是明確或隱含都是禁止的,並且會丟出錯誤訊息。 ```javascript= const e = Symbol(true); const f = Symbol(false); Boolean(e); // true Boolean(f); // true console.log(e); // Symbol(true) console.log(f); // Symbol(false) const g = Symbol(true); const h = Symbol(false); if (g) { console.log('g 是真的'); }// g 是真的 if (h) { console.log('h 是真的'); }// h 是真的 ``` 💬說明:在轉為布林方面,無論是明確或隱含都是可以的,並且結果都是 true。 | Symbol | 明確強制轉型 | 隱含強制轉型 | |:--------:|:------------:|:------------:| | 轉成字串 | ✔️ | ❌ | | 轉成數字 | ❌ | ❌ | | 轉成布林 | ✔️ | ✔️ | ## 5. 有用的功能? OR 缺陷?: 當你對隱含的強制轉型停留在一知半解的階段時,就會覺得這個設計是極大的缺陷;但了解透徹之後,或許它就會變成了有用的功能,減少冗贅、反覆套用與避免過於細節調節的步驟。 | 隱含的強制轉型 | 數字 | 字串 | 布林 | | -------------------------------------- |:----:|:----:|:----:| | 運算類:加( + )法 | | ✔️ | | | 運算類:減( - )乘( * )除( / )法 | ✔️ | | | | if、for、while、三元運算式、邏輯運算子 | | | ✔️ | 💬說明:方便記憶的簡表,詳細內容還是需要爬一下文。 --- #### 參考文章 * [你懂 JavaScript 嗎?#8 強制轉型(Coercion)](https://cythilya.github.io/2018/10/15/coercion/)