ECMAScript 一共定義了七種 build-in types
,其中六種爲 Primitive Value
,Null
, Undefined
,String
, Number
, Boolean
, Symbol
。而最後一種 Object
build-in type 與一般意義上的 JavaScript 中 Object 並不同,總的來講,只要不屬於 Primitive Value 的值,就屬於 Object
類型,好比數組、對象、日期、正則、函數。javascript
每一種基本類型 number
, string
, boolean
, symbol
在 Object(build-in type)
中都有對應的類。所謂裝箱轉換,正是把基本類型轉換爲對應的對象,他是類型轉換中一種至關重要的種類。html
JavaScript 語言設計上試圖模糊對象和基本類型之間的關係,好比,咱們能夠直接在基本類型上使用對象的方法:java
console.log('abc'.charAt()); // a
甚至咱們在原型上添加方法,均可以應用於基本類型。git
其實是 .
運算符提供了裝箱操做,它會根據基礎類型構造一個臨時對象,使得咱們能在基礎類型上調用對應對象的方法。github
在 JavaScript 標準中,規定了 ToPrimitive 函數,它是對象類型到基本類型的轉換(即,拆箱轉換)。segmentfault
對象到 String 和 Number 的轉換都遵循「先拆箱再轉換」的規則。經過拆箱轉換,把對象變成基本類型,再從基本類型轉換爲對應的 String 或者 Number。數組
拆箱轉換會嘗試調用 valueOf 和 toString 來得到拆箱後的基本類型。若是 valueOf 和 toString 都不存在,或者沒有返回基本類型,則會產生類型錯誤 TypeError。函數
ToPrimitive
用於將 Object
轉爲 Primitive Value
ui
對於咱們日常遇到的 Object,其處理邏輯是:設計
Object.valueOf
,若是結果是 Primitive Value
,則返回;Object.toString
,若是結果是 Primitive Value
,則返回;普通對象和數組的這兩個方法返回的結果以下:
var a = [12] var b = {a: 123} // [12] a.valueOf() // '12' a.toString() // {a: 123} b.valueOf() // '[object Object]' b.toString()
如上,二者的 valueOf
返回的都不是 Primitive Value
(返回了自身,仍是 Object
類型)。那麼,根據規範,二者調用 ToPrimitive
返回的將是一個 字符串。
這個方法用於將不是 Boolean
類型的值轉換爲 Boolean
類型。
Undefined
返回 falseNull
返回 falseObject
類型都會被轉換爲 true;Number
類型中,0,NaN 會被轉換爲 false,其它都爲 true其它類型轉換爲 Number
類型。
Undefined
返回 NaNNull
返回 0Boolean
類型,true
爲 1; false
爲 0String
類型,若是知足數字語義則轉爲數字,不然轉換爲 NaNObject
類型,先轉換爲 Primitive Value
再遞歸調用自身 ToNumber 來轉換。// '56' ==> 56 Number([56]) // ',56' ==> NaN Number([,56]) // '55,56' ==> NaN Number([55, 56])
Number
返回 對應數值字符串Boolean
返回字符串 「true」 或者 「false」Undefined
返回 「undefined」Null
返回 「null」瞭解了上面的知識,能夠開始進入咱們的正題了,在 JavaScript 中能夠觸發隱式類型轉換的操做有:
+
, -
, *
, /
==
, <
, >
, >=
, <=
if
, while
console
, alet
輸入時會自動轉換成 String
類型Type
相同,等價於 A === B
undefined == null
String == Number
,則把 String
轉換成 Number
Boolean
值的,將 Boolean
轉換成 Number
Object String/Number/Symbol
,將 Object
轉換成 Primitive Value
// '12' ==> 12; // 返回 true 12 == '12' // 轉 boolean: [] == 0 // 轉 object: '' == 0 // 轉 string: 0 == 0 // 返回 true [] == false // 轉 object: '45' == 45 // 轉 string: 45 == 45 // 返回 true [45] == 45 // 單目: {} == false // 轉 boolean: {} == 0 // 轉 object: '[object Object]' == 0 // 轉 string: NaN == 0 // 返回 false {} == !{} // 單目:[] == fasle // 轉 boolean: [] == 0 // 轉 array: "" == 0 // 轉 string: 0 == 0 // 返回 true [] == ![] [] == [] [] == 0
Number
類型判斷:有 NaN 就 false;SameValueNonNumber
另外 != 和 !== 則是指出了 A != B 與 !(A == B) 是徹底等價的。在判斷 !=/!== 時,其實就是在判斷 ==/===.
ToPrimitive
轉換爲 Primitive Value
因爲 Primitive Value
出來有 String
和 Number
兩種結果,分別有不一樣的比較規則;
// 注意轉換後爲 '45' < '46' // 按字符串規則比較 最終比較的是 '5'.charCodeAt() < '6'.charCodeAt() => 53 < 54 // 返回 true [45] < [46] // 同理 [10] < [9] 最後進行的是 '10' < '9' 的比較,是字符串之間的筆記,不會轉換爲數字間的比較, // 其實最終比較的是 '1'.charCodeAt() < '9'.charCodeAt() => 49 < 57. [10] < [9]
// 每一個表達式是 true 仍是 false 呢?爲啥呢? // 初階 !{} 12 == '12' 'false' == false null == undefined // 高階 [] == [] [] == false [] === false [45] == 45 // 終階 [45] < [46] ? [10] < [9] ? {} == !{} {} != {} -0 === +0 NaN === NaN NaN != NaN // 轉換條件 轉換後類型 結果 []+[] // String 「」 [1,2]+[3,4] // String 「1,23,4」 []+{} // String 「[object Object]」 [1,2] + {a:1} // String 「1,2[object Object]」 {}+[] // Number 0 {}+[1] //Number 1 {a:1}+[1,2] // Number NaN {a:1}+{b:2} // Chrome - String 「[object Object][object Object]」 (背後實現eval) {a:1}+{b:2} // Firefox - Number NaN true+true // Number 2 1+{a:1} // String 「1[object Object]」