# JavaScript隱性轉換、寬鬆相等、嚴格相等 ## 隱性轉換(Implicit Type Conversion) JavaScript 在進行運算時,經常會自動將變數轉型。這一節整理常見隱性轉型的規則 ## +運算子 - 規則一:前後運算元如果其中之一為 “字串” 型別,+ 視為字串運算子 - 規則二:前後運算元如果無法轉型為原始型別(就是指物件型別),+ 視為字串運算子。 - 規則三:上述情況以外,+ 視為算數運算子。 規則一:前後運算元如果其中之一為 “字串” 型別,+ 視為字串運算子。 ```javascript // 結果:'1true' console.log('1' + true); ``` 規則二:前後運算元如果無法轉型為原始型別(就是指物件型別),+ 視為字串運算子 ```jsx= //[]會被轉換成空字串 console.log(1 + []) //{} 單獨轉換時結果是 '[object Object]' console.log(String([])) //{} 轉成 '[object Object]' console.log(1 + {}) //{a:1} 轉成 '[object Object]' console.log(1 + {a:1}) ``` 規則三:上述情況以外,+ 視為算數運算子 ```javascript= // true 轉成 1,1 + 1 = 2 console.log(1 + true); ``` ## 算術運算子( - / *) 一律套用 Number 轉型,ex:true會被轉型成1 ```jsx= //100 console.log(true * 100) //-99 console.log(true - 100) ``` 陣列轉字串再轉數字 ```jsx= // [100,10] -> '100,10' -> Number('100,10') = NaN console.log([100,10] * 100); // NaN ``` ## BigInt 與 Number 型別無法混合計算 Uncaught TypeError: Cannot mix BigInt and other types, use explicit conversions 未捕獲的類型錯誤:無法混合 BigInt 和其他類型,請使用明確轉換 ```jsx= console.log(1 + 1n) ``` Uncaught TypeError: Cannot mix BigInt and other types, use explicit conversions 未捕獲的類型錯誤:無法混合 BigInt 和其他類型,請使用明確轉換 ```jsx= console.log(1n * 1); ``` ## Symbol型別的轉換 JavaScript 不允許隱式地將 `Symbol` 類型的值轉換為數字或字串進行加法運算 Uncaught TypeError: Cannot convert a Symbol value to a number ```jsx= console.log(1 + Symbol(1)); ``` Uncaught TypeError: Cannot convert a Symbol value to a string ```jsx= console.log({} + Symbol(1)); ``` ## 寬鬆相等 Number, String, Boolean 這三者進行比對時,通通都使用 Number 進行轉型 ```jsx= //true console.log('1' == true) //true console.log('1' == 1) //100 console.log(1 == true) ``` **Null 和 Undefined 特殊比較規則** Null不轉型(都是 false),但 null 與 undefined 相比則是 true ```jsx= // null 不會轉成 0,結果是 false console.log(null == 0); // null 不會轉成 '',結果是 false console.log(null == ''); // null 不會轉成 false,結果是 false console.log(null == false); // null 和 undefined 寬鬆比較為 true console.log(null == undefined); // null 和 null 一樣 console.log(null == null); ``` 轉型為「數學值」,沒有 NaN、沒有小數點、沒有最大值 - Number超過安全範圍比較就會出錯 - 如果使用BigInt可保證其精準性 ```jsx= console.dir(Number); console.log(9007199254740993 == '9007199254740992'); console.log(9007199254740993n == '9007199254740992'); ``` ### 物件與非物件比對 物件與其它型別比較時,會透過 “包裹物件” 將物件轉為相同型別 ```jsx= // true - 當陣列只有一個元素時,會先轉換為數字再比較 console.log([0] == 0); // true - 物件會先轉換為字串 '[object Object]' 再比較 console.log('[object Object]' == {}); // [object Object] - 物件轉為字串的預設結果 console.log(String({})); // true - 陣列會先轉換為字串,['a'] 轉為 'a' 再比較 console.log(['a'] == 'a'); ``` 例外: - 布林採用 Number 轉型 - 陣列轉數值,會先 `toString()` 再套用 `Number()` ```jsx= // 空陣列轉成數值是 0,0 == false 為 true console.log([] == false); // true // 空陣列先轉字串再轉成數字,結果是 0 console.log(Number([])); // 0 // 陣列 [1] 轉成字串 "1",再轉成數字 1,1 == true 為 true console.log([1] == true); // true // 陣列 [2] 轉成字串 "2",再轉成數字 2,2 != true 為 false console.log([2] == true); // false ``` Symbol比較,類似於物件是比對記憶體位址,所以此題會是`false` ```jsx= let sym1 = Symbol(1); let sym2 = Symbol(1); console.log(sym1 == sym2); ``` ## 嚴格相等 值的型別需完全一樣 例外狀況: 物件、陣列比對的是記憶體位址 ```jsx= // NaN 不等於 NaN console.log(NaN === NaN); // false // undefined 和 null 型別不同 console.log(undefined === null); // false // 物件比較的是記憶體位址,不是內容 console.log({} === {}); // false // 陣列也是物件,比較的是記憶體位址 console.log([] === []); // false // new Number(1) 創造的是不同物件 console.log(new Number(1) === new Number(1)); // false // a 和 b 是兩個不同的物件,記憶體位址不同 let a = { name: "123" }; let b = { name: "123" }; console.log(a == b); // false // +0 和 -0 在嚴格相等下被視為相等 console.log(+0 === -0); // true ``` ## Number和parseInt的特別狀況: ```jsx= //NaN console.log(Number("100元")); //100 console.log(parseInt("100元")); ``` ## 補充 真假值:https://developer.mozilla.org/zh-CN/docs/Glossary/Truthy 真假值表:https://dorey.github.io/JavaScript-Equality-Table/
×
Sign in
Email
Password
Forgot password
or
By clicking below, you agree to our
terms of service
.
Sign in via Facebook
Sign in via Twitter
Sign in via GitHub
Sign in via Dropbox
Sign in with Wallet
Wallet (
)
Connect another wallet
New to HackMD?
Sign up