Javascript有7種資料類型,包括5種原始類型(也叫原始值)number、Boolean、string、null、undefined 和2種複合類型object、array,它們之間可以根據某種規則相互轉換。《Javascript權威指南》列出了在Javascript中如何進行 類型轉換,如下表:
其中原始值之間的轉換沒什麼可說的,記住就好了,我們要關注的是複合值(即對象)與原始值之間的轉換。原始值轉換成對象直接調用Object()方法即可(null和undefined不可調用該方法),而對象轉換成原始值呢?如空數組[]轉換成數字為什麼是0呢?
對象轉換成原始值
對象轉換成布爾值:所有對象轉換成布爾值都是true,包括封裝對象new Boolean(false)轉換成布爾值也是true。
對象轉換成字串:如果對象有toString()方法,則調用這個方法,如果它返回原始值,將原始值轉換成字 符串後返回;如果對象沒有toString()方法或調用toString()方法方法返回的不是原始值,則調用valueOf()方法,然後將 valueOf()方法返回的原始值轉換成字串返回,如果valueOf()方法返回的還不是原始值,沒救了,瀏覽器只好拋出類型異常的錯誤。
對象轉換成數字:和對象轉換成字串過程類似,只不過先調的是valueOf()方法。
根據以上規則就可以知道為什麼空數群組轉換成數字結果是0了:空數組先調用了valueOf()方法,返回了“”字串,“”字串是個原始值,再根據上面的表格,“”字串轉換成數字0。
隱式類型轉換
來看一個例子:
"123" == 123
大家都知道結果是true,==運算子兩邊的運算元屬於不同的資料類型,要判斷是否相等,需要經過隱式類型轉換成相同的資料類型才行。然而,是運算子左邊的“123”轉換成了數字123還是運算子右邊的123轉換成了字串“123”呢?
規則是:
- 如果一個值是null,另一個是undefined,那麼它們相等
- 如果一個值是數字,另一個是字串,先將字串轉為數字再比較
- 如果其中一個值是true,將true轉為1再比較,同理false轉換成0再比較
- 如果一個值是對象,另一個是數字或字串,則將對象轉換成原始值再進行比較(日期對象轉換成字串,其它對象先嘗試調用valueOf()方法再嘗試使用toString())
- 其它不同類型的比較都不相等
顯然上面的例子屬於第二種情況,“123”被隱式轉換為123了。
除了==運算子,諸如+、-、*、/、!、<、<=、>、>=等運算子兩邊的運算元類型不同時,都會發生隱式類型轉換,還包括while()語句和if()語句內的條件陳述式,alert()語句會將()內的值隱式轉換成字串後再彈出。
“+”運算子
二元加法運算子“+”可以對兩個數字做加法,也可以做字串串連操作:
1 + 1 // 2"hello" + "world" // "hello world"
當二元加法運算子“+”遇到下面的運算時運算元會如何轉換呢?試著想想答案再往下看
1 + true"1" + true1 + "1" {} + 1 {} + {}
隱式轉換規則:
- 如果其中一個運算元是對象,對象會轉換成原始值:日期對象通過toString()方法轉換,其他對象通過valueOf()方法轉換,如果valueOf()傳回值不是原始值再使用toString()方法轉換。
- 在進行了對象到原始值的轉換後,如果其中一個運算元是字串的話,另一個運算元也會轉換為字串,然後進行字串拼接。
- 否則,兩個運算元都將轉換為數字(轉換不了的將轉換為NaN),然後進行加法操作。
根據規則,以上的例子結果是:
1 + true// true轉換為1,然後加法得出結果2"1" + true// true轉換為"true",然後字串拼接得出結果"1true"1 + "1" // 數字1轉換為"1",然後字串拼接得出結果"11"{} + 1 // {}對象調用toString()方法轉換為字串"[object Object]",變成了"[object Object]" + 1,匹配第二條規則,1將轉換為字串"1",然後字串拼接得出結果"[object Object]1"{} + {} // 自己想想過程吧
當“+”做為一元運算子時,會把運算元轉換為數字(轉不了的轉成NaN)
“-”運算子
當“-”做為二元運算子時,會把運算元轉換為數字(轉不了的轉成NaN)
當“-”做為一元運算子時,會把運算元轉換為數字(轉不了的轉成NaN),同時改變運算結果的符合
比較子(">"、">="、"<"、"<=")
比較操作符的運算元可能是任意類型,然而只有數字和字串才能真正執行比較操作,因此其它類型的運算元都將進行類型轉換,具體規則如下:
- 如果運算元為對象,那麼這個對象將轉換為原始值:同上,日期對象通過toString()方法轉換,其他對象通過valueOf()方法轉換,如果valueOf()傳回值不是原始值再使用toString()方法轉換。
- 在對象轉換為原始值後,如果兩個運算元都是字串,將依次比較每個字串的Unicode大小。
- 在對象轉換為原始值後,如果至少有一個運算元不是字串,那麼兩個運算元都將轉換為數字進行比較,如果其中某個運算元無法轉換為數字,這個運算元將轉換為NaN,比較結果為false。
"*"、"/"、"%"、"!"
"*"、"/"、"%"會把運算元轉換為數字(轉不了的轉成NaN)
"!"會把運算元轉換為布爾值