運算過程中由於 Javascript 是弱型別,沒有辦法強制規範型別,所以會在運算過程中發生隱式(動態)型別轉換,稱之為 Corecion。
Converting a value from one type to another.
算術運算子的隱式轉換
1 | const a = 1 + '2'; |
上方範例可以印證 Javascript 引擎將數字 1
與字串 2
相加的過程中產生的動態型別的轉換,獲得了字串 12
。
在某些強型別的語言中,這樣做是會噴 error 的,但 Javascript 不會,這也造成開發過程時常會發生不如預期的結果。
比較運算子的隱式轉換
從以下的範例我們可以很自然地獲得 true 的結果:
1 | const a = 3 > 2 > 1; |
然而以下的範例卻出乎意料之外也獲得了 true:
1 | const a = 3 < 2 < 1; |
這也是動態型別的轉換在作怪,一一拆解一下過程是這樣的,比較運算子 <
在前一篇的相依性有提到:
當運算子相同時會採用相依性的方向來決定計算次序,比較運算子 <
是左相依性(left-to-right associactivity),
所以背後的 Javascript 引擎會如是計算:3 < 2
獲得 false,false < 1
由於型別不同 Javascript 引擎強制將 false 使用數字包裹器轉換為數字型別:
1 | console.log(Number(false)); // 0 |
0 < 1
獲得 true。
強制型轉
型轉分為主動式強制型轉(Explicit Coercion)與被動式隱式型轉(Implicit Coercion),強制型轉有幾個基本型:
- toString
- toNumber
- toBoolean
- toPrimitive
toNumber 數字型轉範例
以下是幾個特殊的案例:
1 | Number(Undefined); // NaN |
雙等號型轉的悲劇
雙等號(double Equality)會造成嚴重的動態型別轉換,引發不可預期的後果,例如以下的範例:
1 | false == 0; // true |
動態型別呼叫的包裹器?
Javascript 引擎在型別轉換背後做了許多事情,但也非沒有規則可循,
以下的範例是 JavaScript 最難以理解的一部分型別轉換:
比較運算子呼叫 toString
1 | [] == false; // true |
這實在是太詭異了!!不過理解一下背後的原理,「當 Array 拿去比較 value 的時候,toString 包裹器會被呼叫,而不是透過 Boolean 轉換」:
1 | String([]); // '' |
有趣的 [object object]
在開發過程查詢 error 或其他型轉情境經常會看見或 alert 噴出 [object object]
這類特殊的值,剖析一下出現的原理:
型轉造成的 [object object]
1 | [] + {}; // '[object object]' |
第一個例子 [] + {};
,這是由於 []
+ 號型轉為空字串 ''
,而 {}
+ 號型轉為 ‘[object object]’ 了;String() 直接調用 .toString
方法來轉換 []
。
第二個例子 {} + []
中, {}
被當作空區塊無作用,只會運算後方的 + []
調用 Number([])
,
依據型轉規則,陣列屬於物件型別所以型轉數字時會調用 toString 方法來型轉成空字串 String([])
獲得 ''
,也就是 Number(‘’),
而獲得 0 的結果。
值得注意的是 block
{}
放置在最前方會被為 Javascript 引擎視作作用域而非空物件!
善用嚴格等式(Tripple Equality)
不同於雙等號造成的型轉悲劇,三等號可以確保最後獲得的比較結果不會被型轉,也能達到預期的值做開發判斷,是比較良好的開發習慣。
評論