JavaScript數(shù)據(jù)類型的轉換詳解
數(shù)據(jù)類型的轉換
概述
JavaScript是一種動態(tài)類型語言,變量沒有類型限制,可以隨時賦予任意值。
var x = y ? 1 : 'a';
上面代碼中,變量x到底是數(shù)值還是字符串,取決于另一個變量y的值。y為true時,x是一個數(shù)值;y為false時,x是一個字符串。這意味著,x的類型沒法在編譯階段就知道,必須等到運行才能知道。
雖然變量的數(shù)據(jù)類型是不確定的,但是各種運算符對數(shù)據(jù)類型是有要求的。如果運算符發(fā)現(xiàn),運算子的類型與預期不符,就會自動轉換類型。比如,減法運算符預期左右兩側的運算子應該是數(shù)值,如果不是,就會自動將它們轉為數(shù)值。
'4' - '3' //1
上面代碼中,雖然是兩個字符串相減,但是依然會得到結果數(shù)值1,原因就在于JavaScript將運算子自動轉為了數(shù)值。
強制轉換
強制轉換主要使用Number()、String()和Boolean()三個函數(shù),手動將各種類型的值,分別轉換成數(shù)字、字符串或者布爾值。
Number()
使用Number函數(shù),可以將任意類型的值轉化成數(shù)值。
下面分成兩種情況討論,一種是參數(shù)是原始類型的值,另一種是參數(shù)是對象。
(1) 原始類型值
原始類型值的轉換規(guī)則如下。
// 數(shù)值:轉換后還是原來的值
Number(324) //324
//字符串:如果可以被解析為數(shù)值,則轉換為相應的數(shù)值
Number('324') //324
//字符串:如果不可以被解析為數(shù)值,返回NaN
Number('324abc') //NaN
//空字符串轉為0
Number('') //0
//布爾值:true轉成1,false轉成0
Number(true) //1
Number(false) //0
//undefined:轉成NaN
Number(undefined) //NaN
//null:轉成0
Number(null) //0
Number函數(shù)將字符串轉為數(shù)值,要比parseInt函數(shù)嚴格的多?;旧?,只要有一個字符無法轉成數(shù)值,整個字符串就會被轉為NaN。
parseInt('42 cats')// 42
Number('42 cats') // NaN
上面代碼中,parseInt諸葛解析字符,而Number函數(shù)整體轉換字符串的類型。
另外,parseInt和Number函數(shù)都會自動過濾一個字符串前導和后綴的空格。
parseInt('\t\v\r12.34\n') //12
Number('\t\v\r12.34\n') //12.34
(2)對象
簡單規(guī)則是,Number方法的參數(shù)是對象時,將返回NaN,除非是包含單個數(shù)值的數(shù)組。
Number({a:1}) //NaN
Number([1,2,3]) //NaN
Number([5]) //5
之所以會這樣,是因為Number背后的轉換規(guī)則比較復雜。
第一步,調用對象自身的valueOf方法。如果返回原始類型的值,則直接對該值使用Number函數(shù),不再進行后續(xù)步驟。
第二步,如果valueOf方法返回的還是對象,則則改為調用對象自身的toString方法。如果toString方法返回原始類型的值,則對該值使用Number函數(shù),不再進行后續(xù)步驟。
第三步,如果toString方法返回的是對象,就報錯。
請看下面的例子。
var obj = {x: 1};
Number(obj) // NaN
// 等同于
if (typeof obj.valueOf() === 'object') {
Number(obj.toString());
} else {
Number(obj.valueOf());
}
上面代碼中,Number函數(shù)將obj對象轉為數(shù)值。背后發(fā)生了一連串的操作,首先調用obj.valueOf方法, 結果返回對象本身;于是,繼續(xù)調用obj.toString方法,這時返回字符串[object Object],對這個字符串使用Number函數(shù),得到NaN。
默認情況下,對象的valueOf方法返回對象本身,所以一般總是會調用toString方法,而toString方法返回對象的類型字符串(比如[object Object])。所以,會有下面的結果。
Number({}) //NaN
如果toString方法返回的不是原始類型的值,結果就會報錯。
var obj = {
valueOf: function () {
return {};
},
toString: function () {
return {};
}
};
Number(obj)
// TypeError: Cannot convert object to primitive value
上面代碼的valueOf和toString方法,返回的都是對象,所以轉成數(shù)值時會報錯。
從上例還可以看到,valueOf和toString方法,都是可以自定義的。
Number({
valueOf:function(){
return 2;
}
})
//2
Number({
toString:function(){
return 3;
}
})
//3
Number({
valueOf:function(){
return 2;
},
toString:function(){
return 3;
}
})
//2
上面代碼對三個對象使用Number函數(shù)。第一個對象返回valueOf方法的值,第二個對象返回toString方法的值,第三個對象表示valueOf方法先于toString方法執(zhí)行。
String()
String函數(shù)可以將任意類型的值轉化成字符串,轉換規(guī)則如下。
(1)原始類型值
- 數(shù)值:轉為相應的字符串。
- 字符串:轉換后還是原來的值。
- 布爾值:
true轉為字符串"true",false轉為字符串"false"。 - undefined:轉為字符串
"undefined"。 - null:轉為字符串
"null"。
String(123) //"123"
String('abc') // "abc"
String(true) //"true"
String(undefined) //"undefined"
String(null) //"null"
(2)對象
String方法的參數(shù)如果是對象,返回一個類型字符串;如果是數(shù)組,返回該數(shù)組的字符串形式。
String({a:1}) //"[object Object]"
String([1,2,3]) //"1,2,3"
String方法背后的轉換規(guī)則,與Number方法基本相同,只是互換了valueOf方法和toString方法的執(zhí)行順序。
- 先調用對象自身的
toString方法。如果返回原始類型的值,則對該值使用String函數(shù),不再進行以下步驟。 - 如果
toString方法返回的是對象,再調用原對象的valueOf方法。如果valueOf方法返回原始類型的值,則對該值使用String函數(shù),不再進行以下步驟。 - 如果
valueOf方法返回的是對象,就報錯。
下面是一個例子。
String({a:1})
// "[object Object]"
//等同于
String({a:1}.toString())
// "[object Object]"
上面代碼先調用對象的toString方法,發(fā)現(xiàn)返回的是字符串[object Object],就不再調用valueOf方法了。
如果toString法和valueOf方法,返回的都是對象,就會報錯。
var obj = {
valueOf:function(){
return {};
},
toString:function(){
return {};
}
};
String (obj)
//TypeError:Cannot convert object to primitive value
下面是通過自定義toString方法,改變返回值的例子。
String({
toString:function(){
retuen 3;
}
})
//"3"
String({
valueOf:function({
return 2;
}
})
// "[object Object]"
String({
valueOf:function(){
return 2;
},
toString:function(){
return 3;
}
})
//"3"
上面代碼對三個對象使用String函數(shù)。第一個對象返回toString方法的值(數(shù)值3),第二個對象返回的還是toString方法的值([object Object]),第三個對象表示toString方法先于valueOf方法執(zhí)行。
Boolean()
Boolean()函數(shù)可以將任意類型的值轉為布爾值。
它的轉換規(guī)則相對簡單:除了以下五個值的轉換結果為false,其他的值全部為true。
undefinednull0(包含-0和+0)NaN''(空字符串)
Boolean(undefined)//false
Boolean(null)//false
Boolean(0)//false
Boolean(NaN)//false
Boolean('')//false
當然,true和false這兩個布爾值不會發(fā)生變化。
Boolean(true) // true Boolean(false) // false
注意,所有對象(包括空對象)的轉換結果都是true,甚至連false對應的布爾對象new Boolean(false)也是true
Boolean({}) // true
Boolean([]) // true
Boolean(new Boolean(false)) // true
所有對象的布爾值都是true,這是因為 JavaScript 語言設計的時候,出于性能的考慮,如果對象需要計算才能得到布爾值,對于obj1 && obj2這樣的場景,可能會需要較多的計算。為了保證性能,就統(tǒng)一規(guī)定,對象的布爾值為true。
自動轉換
下面介紹自動轉換,它是以強制轉換為基礎的。
遇到以下三種情況時,JavaScript 會自動轉換數(shù)據(jù)類型,即轉換是自動完成的,用戶不可見。
第一種情況,不同類型的數(shù)據(jù)互相運算。
123 + 'abc' // "123abc"
第二種情況,對非布爾值類型的數(shù)據(jù)求布爾值。
if ('abc') {
console.log('hello')
} // "hello"
第三種情況,對非數(shù)值類型的值使用一元運算符(即+和-)。
+ {foo: 'bar'} // NaN
- [1, 2, 3] // NaN
自動轉換的規(guī)則是這樣的:預期什么類型的值,就調用該類型的轉換函數(shù)。比如,某個位置預期為字符串,就調用String函數(shù)進行轉換。如果該位置即可以是字符串,也可能是數(shù)值,那么默認轉為數(shù)值。
由于自動轉換具有不確定性,而且不易出錯,建議在預期為布爾值、數(shù)值、字符串的地方,全部使用Boolean、Number和String函數(shù)進行顯式轉換。
自動轉換為布爾值
JavaScript 遇到預期為布爾值的地方(比如if語句的條件部分),就會將非布爾值的參數(shù)自動轉換為布爾值。系統(tǒng)內部會自動調用Boolean函數(shù)。
因此除了以下五個值,其他都是自動轉為true。
undefinednull+0或-0NaN''(空字符串)
下面這個例子中,條件部分的每個值都相當于false,使用否定運算符后,就變成了true。
if(!undefined
&& !unll
&& !0
&& !NaN
&& !''
) {
console.log('true');
} //true
下面兩種寫法,有時也用于將一個表達式轉為布爾值。它們內部調用的也是Boolean函數(shù)。
// 寫法一 expression ? true : false // 寫法二 !! expression
自動轉換為字符串
JavaScript 遇到預期為字符串的地方,就會將非字符串的值自動轉為字符串。具體規(guī)則是,先將復合類型的值轉為原始類型的值,再將原始類型的值轉為字符串。
字符串的自動轉換,主要發(fā)生在字符串的加法運算時。當一個值為字符串,另一個值為非字符串,則后者轉為字符串。
'5' + 1 // '51'
'5' + true // "5true"
'5' + false // "5false"
'5' + {} // "5[object Object]"
'5' + [] // "5"
'5' + function (){} // "5function (){}"
'5' + undefined // "5undefined"
'5' + null // "5null"
這種自動轉換很容易出錯。
var obj = {
width: '100'
};
obj.width + 20 // "10020"
上面代碼中,開發(fā)者可能期望返回120,但是由于自動轉換,實際上返回了一個字符10020。
自動轉換為數(shù)值
JavaScript 遇到預期為數(shù)值的地方,就會將參數(shù)值自動轉換為數(shù)值。系統(tǒng)內部會自動調用Number函數(shù)。
除了加法運算符(+)有可能把運算子轉為字符串,其他運算符都會把運算子自動轉成數(shù)值。
'5' - '2' // 3 '5' * '2' // 10 true - 1 // 0 false - 1 // -1 '1' - 1 // 0 '5' * [] // 0 false / '5' // 0 'abc' - 1 // NaN null + 1 // 1 undefined + 1 // NaN
上面代碼中,運算符兩側的運算子,都被轉成了數(shù)值。
注意:null轉為數(shù)值時為0,而undefined轉為數(shù)值時為NaN。
一元運算符也會把運算子轉成數(shù)值。
+'abc' // NaN -'abc' // NaN +true // 1 -false // 0
到此這篇關于JavaScript數(shù)據(jù)類型的轉換詳解的文章就介紹到這了,更多相關JavaScript數(shù)據(jù)類型轉換內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
基于javascript實現(xiàn)日歷功能原理及代碼實例
這篇文章主要介紹了基于javascript實現(xiàn)日歷效果原理及代碼實例,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下2020-05-05
JavaScript 驗證瀏覽器是否支持javascript的方法小結
一些網(wǎng)站只有客戶端js的驗證,這樣就給一些hacher一些可趁之機了,不信大家測試一些網(wǎng)站的注冊功能看看,有部分網(wǎng)站只有客戶端驗證,我為了達到客戶端驗證,先是判斷瀏覽器是否支持js,如果不支持,提示信息,然后屏蔽掉發(fā)送按鈕2009-05-05

