JavaScript型別轉換
1.原始值到原始值的轉換
1.原始值轉化為布林值
所有的假值(undefined、null、0、-0、NaN、””)會被轉化為 false,其他都會被轉為 true。
2.原始值轉化為字串
都相當於 原始值 + “”
注意:null和undefined這兩個值沒有toSting()方法,但是可以通過+""方法或者通過String()函式轉換成字串。
var a = null+" "
typeof a //string
var b = String(null);
typeof b //string
x+""相當於 String(x)。
3.原始值轉化為數字
+" 66" // 66 +" 6 7 " // NaN
布林轉數字:true -> 1, false -> 0
字串轉數字:以數字表示的字串可以直接會轉為字串,如果字串頭尾有空格會忽略,但是空格在中間,轉換結果就是 NaN。
2.原始值到物件的轉換
null 和 undefined 轉物件直接拋異常。
原始值通過呼叫 String()、Number()、Boolean()建構函式,轉換為他們各自的包裝物件。
3.物件到原始值的轉換
1.物件轉化為布林都為true
2.物件到字串:
如果物件有 toString() 方法,就呼叫 toString() 方法。如果該方法返回原始值,就講這個值轉化為字串。 如果物件沒有 toString() 方法或者 該方法返回的不是原始值,就會呼叫該物件的 valueOf() 方法。如果存在就呼叫這個方法,如果返回值是原始值,就轉化為字串。
3.物件到數字
物件轉化為數字做了跟物件轉化為字串做了想同的事兒,不同的是後者是先呼叫 valueOf 方法,如果呼叫失敗或者返回不是原始值,就呼叫 toString 方法。
4.補充
一些常用內建物件toString方法和valueOf的轉換規則。
toString相關:
valueOf相關:
附註:![]轉換成!true,但是[]轉換成0,[true]轉換成1.[]非空就轉換成1
4.==運算子如何進行型別轉換
1.如果一個值是null,另一個值是undefined,則相等
2.如果一個是字串,另一個值是數字,則把字串轉換成數字,進行比較
3.如果任意值是true,則把true轉換成1再進行比較;如果任意值是false,則把false轉換成0再進行比較
4.如果一個是物件,另一個是數值或字串,把物件轉換成基礎型別的值再比較。物件轉換成基礎型別,利用它的 toString 或者 valueOf 方法。 js 核心內建類,會嘗試 valueOf 先於 toString(可以理解為物件優先轉換成數字);例外的是 Date,Date 利用的是 toString 轉換。非 js 核心的物件,通過自己的實現中定義的方法轉換成原始值。
5.+運算子如何進行型別轉化
1.如果作為一元運算子就是轉化為數字,常常用來將字串轉化為數字
+"2" //2
+false //0
2.如果作為二元運算子就有兩種轉換方式
- 兩邊如果有字串,另一邊一會轉化為字串進行相加
- 如果沒有字串,兩邊都會轉化為數字進行相加,物件也根據前面的方法轉化為原始值數字。
- 如果其中的一個運算元是物件,則將物件轉換成原始值,日期物件會通過 toString() 方法進行轉換,其他物件通過 valueOf()方法進行轉換,但是大多數方法都是不具備可用的 valueOf() 方法,所以還是會通過 toString() 方法執行轉換。
流程圖如下:
6.實戰分析
1.[]+[] // ""
_1. 首先運算子是 + 運算子而且很明顯是二元運算子,並且有物件,所以選擇最後一點,運算元是物件,將物件轉換為原始值。
_2. 兩邊物件都是陣列,左邊的陣列先呼叫 valueOf() 方法無果,然後去呼叫 toString(), 方法,在 toString() 的轉化規則裡面有『將陣列轉化為字串,用逗號分隔』,由於沒有其他元素,所以直接是空字串 “”。
_3. 因為加號有一邊是字串了,所以另外一邊也轉為 字串,所以兩邊都是空字串 “”。
_4. 所以加起來也是空字串 “”。
(! + [] + [] + ![]).length // 9
_1. 首先我們會看到挺多一元運算子,「+」、「!」,對於一元運算子是右結合性,所以可以畫出以下運算順序。
_2. 對於+[],陣列是會被轉化為數字的而不是字串,可見「+ 運算子如何進行型別轉化」的第一條,所以經過第一步就會轉化為
(!0 + [] + “false”).length
_3. 第二步比較簡單,0 轉化為布林值就是 false,所以經過第二步就轉化為
(true + [] + “false”).length
_4. 第三步中間的 []會轉為空字串,在「+ 運算子如何進行型別轉化」第二條的第三點,物件會被轉轉化為原始值,就是空字元,所以經過第三步之後就會變成
(“true” + “false”).length
_5. 第五步就比較簡單啦,最終就是
附錄:
下面是一些補充:
1.對資料型別有期待的語句和表示式:
1、期待boolean型別的 : if 語句 、 do while 語句 、 while do 語句 、 && || ! (與或非邏輯表示式) 、 ? : ( 三目運算子)
2、期待number型別的 : + - * / % (算數運算子) 、 ++ – (增量/減量運算子) 、 > 、 >= 、 < 、 <= 數字比較
3、期待字串的: + (字串連線) 、 > 、 >= 、 < 、 <= 字母排序比較
4、特殊的 : == 、 != (不)相等運算子,在檢測兩個運算元是否相等時,會進行型別轉換;(注意 : === 、!== 是(不)嚴格相等運算子,是不會進行型別轉換的)
需要說明的是,1中當然可以傳入表示式,但是表示式返回的結果也肯定會返回boolean型別的值,或者返回值被轉換為boolean;2和3有一些重複的運算子 : + 、 > 、 >= 、 < 、 <= ,這些運算子在不同場景下發生自動轉換的時候,會有不同的優先順序。
有如下場景:
1 + 1 // 2
'1' + '1' // '11'
'1' + 1 // "11"
'1' + null // "1null"
'1' + {} // "1[object Object]"
'1' + new Date() // "1Wed Jun 20 2018 11:49:55 GMT+0800 (中國標準時間)"
1 + {} // "1[object Object]"
1 + new Date() // "1Wed Jun 20 2018 11:56:56 GMT+0800 (中國標準時間)"
1 + [] // "1"
1 + null // 1
從例子中可以看到,+ 的轉換其實是優先轉換為字串的,如果有一個運算元是物件的話,會轉化為原始值(除了Date物件是呼叫toString()方式轉換 , 其他物件都會呼叫 valueOf() 進行轉換 , 但是由於多數物件只是簡單的繼承了valueOf() , 只會返回物件,而不是一個原始值,所以會再呼叫toString進行轉換) , 所以這裡可以簡單的理解為:都會轉換為字串 。 另一個運算元也會轉換為字串.
“+”還有特殊的用法,就是轉換為數字,如下。
+ null // 0
+ undefined // NaN
+ {} // NaN
+ new Date() // 1529467646682
+ ["5"] // 5
+ "4" // 4
+{} //NaN
+[] //0
> 、 >= 、 < 、 <= 這些比較運算子的規則和 + 類似,不過是會優先轉換為數字進行比較。
// 作用 : 比較數值大小或者再字母表中的位置。也是期待數字和字串!
1、兩個運算元中只要有一個不是字串,則兩個值都轉為數字
"3" > "11" // true 字串比較
3 > "11" // false 11 轉換為數字
true > '0' // true true 和 ‘0’ 都轉換為數字
2、物件同樣會轉換為原始值(不過這裡的Date物件也是優先呼叫valueOf ,返回的是毫秒數,其他的和上述 + 的一樣),如果轉換後有一個字不是字串,則兩個值也都需要轉換為數字
1000 > new Date() // false
100000000000000000000000 > new Date() // true date物件轉換為數字
"100000000000000000000000" > new Date() // true 左值也隨著 date物件一起轉換為數字
'11' > ["3"] // false 陣列轉為字串,所以這裡是字串比較