× 目錄 [1]原始值 [2]對象 [3]顯式[4]隱式 前面的話 所有程式設計語言的重要特征是具有進行類型轉換的能力,javascript給開發者提供了大量簡單的類型轉換方法。javascript是一門弱類型語言,所以類型轉換成為其比較複雜的一部分。本文將從原始值轉換成原始值、對象轉換成原始值、顯 ...
×
目錄
[1]原始值 [2]對象 [3]顯式[4]隱式前面的話
所有程式設計語言的重要特征是具有進行類型轉換的能力,javascript給開發者提供了大量簡單的類型轉換方法。javascript是一門弱類型語言,所以類型轉換成為其比較複雜的一部分。本文將從原始值轉換成原始值、對象轉換成原始值、顯式類型轉換和隱式類型轉換這四方面來詳細介紹javascript中的數據類型轉換
原始值轉換成原始值
【Undefined】
轉換為字元串: 'undefined'
轉換為數字: NaN
轉換為布爾值: false
【Null】
轉換為字元串: 'null'
轉換為數字: 0
轉換為布爾值: false
【Boolean】
true 轉換為字元串: 'true' 轉換為數字: 1 |
false 轉換為字元串: 'false' 轉換為數字: 0 |
【Number】
10 轉換為字元串: '10' 轉換為布爾值: true |
0 轉換為字元串: '0' 轉換為布爾值: false |
NaN 轉換為字元串: 'NaN' 轉換為布爾值: false |
Infinity 轉換為字元串: 'Infinity' 轉換為布爾值: true |
【String】
'abc' 轉換布爾值: true |
'123' 轉換布爾值: true |
' '(空格字元串) 轉換布爾值: true |
''(空字元串) 轉換布爾值: false |
對象轉換成原始值
【Boolean】
對象到布爾值的轉換非常簡單,所有的對象都轉換為true
console.log(Boolean([]));//true console.log(Boolean([12]));//true console.log(Boolean({}));//true console.log(Boolean(/\d/));//true
【Number】
對象轉換成數字的過程,需要經過下列三步:
【1】如果對象具有valueOf()方法,後者返回一個原始值,則javascript將這個原始值轉換為數字(如果需要的話),並返回這個數字
【2】否則,如果對象具有toString()方法,後者返回一個原始值,則javascript將其轉換並返回
【3】否則,javascript拋出一個類型錯誤異常
總結來說,就是先valueOf(),再toString()
var test1 = { toString: function(){ return 1; }, valueOf: function(){ return 2; } } console.log(Number(test1));//2
var test2 = { toString: function(){ return 1; }, } console.log(Number(test2));//1
var test3 = {}; console.log(Number(test3));//NaN
在第一步中,在內置對象中,只有時間Date()對象返回的是原始類型的值數字,所以Number(new Date())返回現在到1970年1月1日00:00:00的數值類型的毫秒數
Number(new Date())//1465976459108
在第二步中,數組Array類型返回由數組中每個值的字元串形式拼接而成的一個以逗號分隔的字元串,如果字元串中只存在數字,則返回數字,其他情況返回NaN;由於其他對象的toString()方法返回的字元串中不只包括數字,所以返回NaN
Number([]);//0 Number([0]);//0 Number([-0]);//0 Number([10]);//10 Number([1,2]);//NaN Number(其他對象);//NaN
【String】
類似地,javascript中對象到字元串的轉換經過瞭如下步驟:
【1】如果對象具有toString()方法,則調用這個方法,如果它返回一個原始值,javascript將這個值轉換為字元串(如果本身不是字元串的話),並返回這個字元串結果
【2】如果對象沒有toString()方法,或者這個方法不返回一個原始值,那麼javascript會調用valueOf()方法,如果存在這個方法,則javascript調用它,如果返回值是原始值,javascript將這個值轉換為字元串(如果本身不是字元串的話),並返回這個字元串結果
【3】否則,javascript無法從toString()或valueOf()獲得一個原始值,因此這時它將拋出一個類型錯誤異常
var test1 = { toString: function(){ return '1'; }, valueOf: function(){ return '2'; } } console.log(String(test1));//'1'
var test2 = { toString: function(){ return {}; }, valueOf: function(){ return '2'; } } console.log(String(test2));//'2'
var test3 = {}; console.log(String(test3));//[object Object]
內置對象都從Object對象繼承了toString()方法
【1】對象Object類型返回'[object Object]'字元串
console.log(({}).toString());//[object Object] console.log(({a:123}).toString());//[object Object]
【2】函數Function類型返回函數代碼
function test(){ alert(1);//test } test.toString();/*"function test(){ alert(1);//test }"*/
【3】數組Array類型返回由數組中每個值的字元串形式拼接而成的一個以逗號分隔的字元串
console.log([].toString());//'' console.log([1].toString());//'1' console.log([1,2,3,4].toString());//'1,2,3,4'
【4】時間Date類型返回表示當前時區的時間的字元串表示
console.log((new Date()).toString());//"Sun Jun 05 2016 10:04:53 GMT+0800 (中國標準時間)"
【5】正則表達式RegExp類型返回正則表達式字面量的字元串表示
console.log(/ab/i.toString());//'/ab/i' console.log(/mom( and dad( and baby)?)?/gi.toString());//'mom( and dad( and baby)?)?/gi'
顯式類型轉換
顯式類型轉換又稱為強制類型轉換,接下來將分別介紹轉成布爾、轉成數字和轉字元串的強制類型轉換
【轉成布爾】
將一個值轉為布爾值可使用Boolean()轉型函數
假值
轉換成false的值稱為假值(falsy value),這7個值包括undefined、null、+0、-0、NaN、false、""(空字元串)
console.log(Boolean(undefined));//false console.log(Boolean(null));//false console.log(Boolean(0));//false console.log(Boolean(-0));//false console.log(Boolean(NaN));//false console.log(Boolean(''));//false console.log(Boolean(false));//false
[註意]在Number()方法中空字元串和空白字元串都轉換為0,而在Boolean()方法中,空字元串""轉換為false,而空白字元串" "轉換為true
console.log(Number(''));//0 console.log(Number(' '));//0 console.log(Boolean(''));//false console.log(Boolean(' '));//true
除了這7個假值外,其他的值轉換為布爾值都是true,也稱為真值(truthy value)
[註意]所有對象(包括空對象)的轉換結果都是true,甚至連false對應的布爾對象new Boolean(false)也是true
console.log(Boolean({}));//true console.log(Boolean([]));//true console.log(Boolean(new Boolean(false)));//true console.log(Boolean(false));//false console.log(Boolean(new Boolean(null)));//true console.log(Boolean(null));//false
【轉成數值】
有3個函數可以把非數值轉換成數值:Number()、parseInt()和parseFloat()。其中Number()可以將任意類型的值轉化成數值,而parseInt()和parseFloat()只應用於字元串向數字的轉換
Number()
當把Number()當作一個函數來調用,而不是作為構造器,它執行一個類型轉換。使用Number()函數可以將任意類型的值轉化成數值
// 數值:十進位數字 console.log(Number(11),Number(011),Number(0x11));//11 9 17 // undefined:轉成 NaN Number(undefined) // NaN // null:轉成0 Number(null) // 0 // 布爾值:true 轉成1,false 轉成0 console.log(Number(true),Number(false));//1 0
Number()函數解析字元串時會識別出字元串的前置空格並去掉
【1】若字元串只包含十進位或十六進位數字,則轉成十進位的數字
[註意1]Number()不識別八進位數字的字元串,會按照十進位數字處理
[註意2]字元串'1.2.'不會報錯,但數字1.2.會報錯
【2】若字元串為空字元串或空格字元串,則轉成0
【3】其他情況的字元串,則轉成NaN
console.log(Number(' 123'));//123 console.log(Number('1.2.'));//NaN console.log(Number(1.2.));//報錯 console.log(Number(''),Number(' '));//0 0 console.log(Number('11'),Number('011'),Number('0x11'));//11 11 17 console.log(Number('abc'));//NaN console.log(Number('123abc'));//NaN
Number()函數解析對象的步驟在上部分已經詳細介紹過,就不再贅述
parseInt()
【1】parseInt()專門用於把字元串轉換成整數。在轉換字元串時,會忽略字元串前面的空格,直到找到第一個非空格字元。如果第一個字元不是數字字元或者負號,parseInt()就會返回NaN。如果是,則繼續解析,直到解析完成或者遇到非數字字元
console.log(parseInt(' 123.1px'));//123 console.log(parseInt(' 123.1 '));//123 console.log(parseInt(' -123.1px'));//-123 console.log(parseInt('a123.1px'));//NaN console.log(parseInt('0 123.1px'));//0
【2】parseInt()可以識別出各種進位的數字,輸出的是運算後的十進位的數字,如1.0或1.或01會以1輸出。在解析八進位字面量的字元串,ECMAScript3會解析八進位,但ECMAScript5沒有解析八進位的能力
console.log(parseInt('11'));//11 console.log(parseInt(11));//11 console.log(parseInt('11.1'));//11 console.log(parseInt(11.1));//11 console.log(parseInt('011'));//11 console.log(parseInt(011));//9 console.log(parseInt('011.1'));//11 console.log(parseInt(011.1));//報錯 console.log(parseInt('0x11'));//17 console.log(parseInt(0x11));//17 console.log(parseInt('0x11.1'));//17 console.log(parseInt(0x11.1));//報錯
[註意]對於那些會自動轉為科學計數法的數字,parseInt會將科學計數法的表示方法視為字元串,因此導致一些奇怪的結果
console.log(parseInt(1000000000000000000000.5)); // 1 // 等同於 console.log(parseInt('1e+21')); // 1 console.log(parseInt(0.0000008)); // 8 // 等同於 console.log(parseInt('8e-7')); // 8
【3】parseInt()
方法還可以接受第二個參數(2到36之間),表示被解析的值的進位,返回該值對應的十進位數。預設情況下,parseInt
的第二個參數為10,即預設是十進位轉十進位
console.log(parseInt('11',2));//3 console.log(parseInt('11',8));//9 console.log(parseInt('11',10));//11 console.log(parseInt('11',16));//17
如果第二個參數不是數值,會被自動轉為一個整數。這個整數只有在2到36之間,才能得到有意義的結果,超出這個範圍,則返回NaN。如果第二個參數是0、undefined和null,則直接忽略
console.log(parseInt('10', 37)); // NaN console.log(parseInt('10', 1)); // NaN console.log(parseInt('10', 0)); // 10 console.log(parseInt('10', null)); // 10 console.log(parseInt('10', undefined)); // 10
如果字元串包含對於指定進位無意義的字元,則從最高位開始,只返回可以轉換的數值。如果最高位無法轉換,則直接返回NaN
console.log(parseInt('1546', 2)); // 1 console.log(parseInt('546', 2)); // NaN
【4】parseInt()是專門用來處理字元串轉換數字的,parseInt處理非字元串和數字類型時輸出NaN。但是,實際上parseInt()包含著隱式的toString()方法,所以parseInt([數字或字元串])輸出對應的數字
console.log(parseInt(null),parseInt(undefined));//NaN NaN console.log(parseInt(true),parseInt(false));//NaN NaN console.log(parseInt([]),parseInt(['2.5px']),parseInt([2.5]));//NaN 2 2 console.log(parseInt(''),parseInt(' '),parseInt({}));//NaN NaN NaN
parseFloat()
【1】parseFloat()專門用於字元串轉換浮點數。同樣地,解析時會忽略字元串前面的空格,直到找到第一個非空格字元,然後一直解析到字元串末尾或一個無效的浮點數字字元為止
console.log(parseFloat(' 0123.px'));//123 console.log(parseFloat(' 123.px'));//123 console.log(parseFloat(' 123.1px'));//123.1 console.log(parseFloat(' 123.1.2px '));//123.1 console.log(parseFloat(' -123.0px'));//-123 console.log(parseFloat('.123.1px'));//0.123 console.log(parseFloat('0 123px'));//0
[註意]如果字元串符合科學計數法,則會進行相應的轉換
console.log(parseFloat('314e-2')); // 3.14 console.log(parseFloat('0.0314E+2')); // 3.14
【2】parseFloat()可以識別不同進位的數字,但只能解析十進位字元串
console.log(parseFloat('11'));//11 console.log(parseFloat(11));//11 console.log(parseFloat('11.1'));//11.1 console.log(parseFloat(11.1));//11.1 console.log(parseFloat('011'));//11 console.log(parseFloat(011));//9 console.log(parseFloat('011.1'));//11.1 console.log(parseFloat(011.1));//報錯 console.log(parseFloat('0x11'));//0 console.log(parseFloat(0x11));//17 console.log(parseFloat('0x11.1'));//0 console.log(parseFloat(0x11.1));//報錯
【3】parseFloat()是專門用來處理字元串轉換浮點數的,parseFloat處理非字元串和數字類型時輸出NaN。但是,實際上parseFloat()包含著隱式的toString()方法,所以parseFloat([數字或字元串])輸出對應的數字
console.log(parseFloat(null),parseFloat(undefined));//NaN NaN console.log(parseFloat(true),parseFloat(false));//NaN NaN console.log(parseFloat([]),parseFloat([2.1]),parseFloat(['2.1px']));//NaN 2.1 2.1 console.log(parseFloat(''),parseFloat({}));//NaN NaN
[註意]Number('')的結果是0,parseInt('')和parseFloat('')的結果是NaN
【轉字元串】
把一個值轉換為字元串有兩種方式,toString()和String()
toString()
第一種是使用幾乎每個值都有的toString()方法,這個方法返回相應值的字元串表現
[註意]undefined和null沒有該方法
undefined.toString();//錯誤 null.toString();//錯誤 true.toString();//'true' false.toString();//'false' 'abc'.toString();//'abc' 1.23.toString();//'1.23' ({}).toString();//[object Object] [1,2,3,4].toString();//'1,2,3,4' (new Date()).toString();//"Sun Jun 05 2016 10:04:53 GMT+0800 (中國標準時間)" /ab/i.toString();//'/ab/i'
String()
在不知道要轉換的值是不是undefined或null時,可以使用轉型函數String()
轉型函數String()遵循下列規則:
【1】如果值是null,則返回'null';如果值是undefined,則返回'undefined'
【2】如果值不是null或undefined,則調用toString()方法並返回原始類型值
【3】若使用toString()方法返回的是對象,則再調用valueOf()方法返回原始類型值,若使用valueOf()方法返回的是對象,會報錯
隱式類型轉換
隱式類型轉換又稱為自動類型轉換,javascript中的運算符和語句中存在著大量的自動類型轉換,其規則是:預期什麼類型的值,就調用該類型的轉換函數。類似地,將隱式類型轉換分為轉為布爾、轉為數值和轉字元串
【轉為布爾】
【1】邏輯非運算符(!)首先會將它的操作數轉換成一個布爾值,然後再對其求反。如果同時使用兩個邏輯非操作符,實際上就會模擬Boolean()轉型函數的行為
console.log(!!undefined);//false console.log(!!null);//false console.log(!!0);//false console.log(!!-0);//false console.log(!!NaN);//false console.log(!!'');//false console.log(!!false);//false
【2】條件運算符(?:)首先會將它問號(?)前的第一個操作數轉換成一個布爾值,如果它是真值,那麼將計算第二個操作數,並返回其計算結果。否則,如果第一個操作數是假值,那麼將計算第三個操作數,並返回其計算結果
console.log(true ? 1 : 0);//1 console.log({} ? 1 : 0);//1 console.log([123] ? 1 : 0);//1 console.log('' ? 1 : 0);//0
【3】if條件語句的條件的求值結果會轉換為一個布爾值,其實條件運算符只是條件語句的簡寫形式
var a = 1; if(a){console.log(1)};//1 if(10){console.log(1)};//1
【4】類似地,while迴圈語句的條件的求值結果也會轉換為一個布爾值
var a = 1; while(a){ console.log(1); break; };//1 while(10){ console.log(1); break; }//1
【轉為數字】
【1】算術運算符將它的操作數轉為數字
var a = '123'; console.log(+a);//123 console.log(a-0);//123 console.log(a*1);//123 console.log(a/1);//123 console.log(a%Infinity);//123
[註意]在涉及到加法的運算中,對象轉換為原始值(先toString()後valueOf())後,如果兩個操作數都不是字元串,則兩個操作數都將轉換成數字
console.log(undefined + undefined);//NaN console.log(null + null);//0 console.log(true + true);//2
【2】位運算符將它的操作數轉為數字
var a = '123'; console.log(~~a);//123 console.log(a & 1);//1 console.log(a | 0);//123 console.log(a ^ 0);//123 console.log(a<<0);//123 console.log(a>>0);//123 console.log(a>>>0);//123
[註意]除了按位與(&)操作之外,其他運算符都可以實現小數取整的效果
【3】涉及關係運算符(==、!=、>=、>、<、<=)的運算中,對象轉換為原始值(先valueOf()後toString())後,如果至少有一個操作數不是字元串,則兩個操作數都將通過Number()轉型函數轉換成數字進行數值比較
console.log([1] == 1);//true,相當於1 == 1 console.log([] == true);//false,相當於0 == 1 console.log({} > true);//false,相當於 NaN > 1 console.log('true' <= 0);//false,相當於NaN <= 0
【轉字元串】
【1】在涉及加法運算符的運算中,對象轉換為原始值(先toString()後valueOf())後,只要有一個操作數是字元串,另一個操作數也會轉換成字元串
console.log(1 + {});//'1[object Object]' console.log(1 + [1,2]);//'11,2' console.log(1 + new Date());//'Fri Jul 15 2016 22:12:05 GMT+0800 (中國標準時間)' console.log(1 + /0/);//'1/0/' console.log('' + undefined);//'undefined' console.log('' + null);//'null' console.log('' + false);//'false' console.log('' + true);//'true'
【2】在涉及關係運算符(==、!=、>=、>、<、<=)的運算中,在對象轉換為原始值(先valueOf()後toString())之後,如果兩個操作數都是字元串,則進行字元串的比較
console.log(new Date() == 'Fri Jul 15 2016 22:12:05 GMT+0800 (中國標準時間)');//true
[註意]一個值轉換為另一個值並不意味著兩個值相等
console.log(Number(null));//0 console.log(null == 0);//false console.log(Boolean(NaN));//false console.log(NaN == false);//false
參考資料
【1】 ES5/類型轉換與測試 https://www.w3.org/html/ig/zh/wiki/ES5/conversion
【2】 阮一峰Javascript標準參考教程——基本語法 http://javascript.ruanyifeng.com/grammar/conversion.html
【3】 W3School-Javascript高級教程——類型轉換 http://www.w3school.com.cn/js/pro_js_typeconversion.asp
【4】《javascript權威指南(第6版)》第3章 類型、值和變數
【5】《javascript高級程式設計(第3版)》第3章 基本概念