文章出處

前面的話

  所有程序設計語言的重要特征是具有進行類型轉換的能力,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
  轉換為數字: NaN

'123'

  轉換布爾值: true
  轉換為數字: 123

' '(空格字符串)

  轉換布爾值: true
  轉換為數字: 0

''(空字符串)

  轉換布爾值: false
  轉換為數字: 0

 

對象轉換成原始值

【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章 基本概念


文章列表


不含病毒。www.avast.com
arrow
arrow
    全站熱搜
    創作者介紹
    創作者 大師兄 的頭像
    大師兄

    IT工程師數位筆記本

    大師兄 發表在 痞客邦 留言(0) 人氣()