JS顯性資料型別轉換和隱性資料型別轉換
一、JS需要型別轉換的原因
JS是一種弱型別語言,變數沒有型別限制,可以隨意賦值。如:
var a=5;
console.log(typeof a);//number
a='我是字串';
console.log(typeof a);//string
如上所示,當把數字5賦值給a變數時,a變數的型別是number,當把字串“我是字串”賦值給變數a時,a變數的型別是string。
雖然變數沒有型別限制,但運算子要求進行運算的變數的型別和運算子期望的型別一致,所以,當不同型別的變數進行加減運算時,就會進行型別轉換(如,1+'a'、'3'-'1')。型別轉換主要分為兩種:強制(顯性)型別轉換和自動(隱性)型別轉換
二、強制(顯性)型別轉換
強制型別轉換主要是指通過String、Number和Boolean等構造方法手動轉換成對應的字串、數字和布林值。
2.1、將其他型別轉為字串
字串是JS的基本資料型別之一,使用String物件的構造方法可以將任意型別的資料轉換為字串,其中,這裡的任意型別主要分為兩大類:原始(基本)型別和物件型別。基本型別的轉換相對簡單,轉換方法如下:
基本資料型別 | String型別 |
---|---|
數字 | 對應的數字字串 |
true | 字串true |
false | 字串false |
null | 字串null |
undefined | 字串undefined |
console.log(String(123));//"123"
console.log(String(true));//"true"
console.log(String(false));//"false"
console.log(String(null));//"null"
console.log(String(undefined));//"undefined"
物件型別的轉換稍微複雜些,物件參與基本型別資料運算時,首先是要將物件轉換為基本型別。轉換方法如下:
1、呼叫toString()方法,如果返回基本型別的值,則用String()構造方法轉換該值。
2、如果toString()方法返回的不是基本型別,則再呼叫valueOf()方法,如果返回基本型別的值,則用String()構造方法轉換該值。
3、如果valueOf()方法返回的也不是基本型別,就丟擲錯誤,如谷歌丟擲:Uncaught TypeError: Cannot convert object to primitive value
如下,為了方便檢視,重寫了String的toString()和valueOf()方法:
例1、當String物件的toString()方法返回基本型別時
//重寫Date物件的toString()
Date.prototype.toString=function(){
console.log('執行了toString(),這裡返回數字1');
return 1;
};
//重寫Date物件的valueOf()方法
Date.prototype.valueOf=function(){
console.log('執行了valueOf()方法,這裡返回數字2');
return 2;
};
var date=new Date();
var str=String(date);
輸出結果:
執行了toString(),這裡返回數字1
列2、當toString()方法返回非基本型別時,再次呼叫valueOf()方法
//重寫Date物件的toString()
Date.prototype.toString=function(){
console.log('執行了toString(),這裡返回數字1');
return {};
};
//重寫Date物件的valueOf()方法
Date.prototype.valueOf=function(){
console.log('執行了valueOf()方法,這裡返回數字2');
return 2;
};
var date=new Date();
var str=String(date);//先呼叫toString()方法,由於返回的不是基本資料型別,再次呼叫valueOf()方法
輸出結果:
執行了toString(),這裡返回數字1
執行了valueOf()方法,這裡返回數字2
例3、toString()和valueOf()都返回的不是基本資料型別,則丟擲異常
//重寫Date物件的toString()
Date.prototype.toString=function(){
console.log('執行了toString(),這裡返回數字1');
return {};
};
//重寫Date物件的valueOf()方法
Date.prototype.valueOf=function(){
console.log('執行了valueOf()方法,這裡返回數字2');
return {};
};
var date=new Date();
var str=String(date);//先呼叫toString()方法,由於返回的不是基本資料型別,再次呼叫valueOf()方法,但還是返回非基本資料型別,所以丟擲異常
輸出結果:
執行了toString(),這裡返回數字1
執行了valueOf()方法,這裡返回數字2
Uncaught TypeError: Cannot convert object to primitive value
也可以採用如下方式驗證:
var obj={
valueOf:function(){
console.log('執行了valueOf()方法,這裡返回數字2');
return 2;
},
toString:function(){
console.log('執行了toString(),這裡返回物件');
return 1;
}
};
String(obj);
2.2、將其他型別轉換成數字
使用Number建構函式轉化任意型別的值時,也分為兩種:一種是將基本型別的值轉換成數字,一種是將物件型的值轉換為數字。基本型別的資料轉換數字的規則如下:
基本資料型別 | 數字型別 |
---|---|
數字字串 | 對應的數字 |
true | 1 |
false | 0 |
null | 0 |
undefined | NaN |
空字串 | 0 |
不可完全被解析為數值的字串 | NaN |
如下:
console.log(Number(123));//123
console.log(Number('123'));//123
console.log(Number('123a'));//NaN
console.log(Number(''));//0
console.log(Number(true));//1
console.log(Number(false));//0
console.log(Number(undefined));//NaN
console.log(Number(null));//0
console.log(Number(' \t\n 3.23322\t '));//Number可以自動去掉兩頭空白符,輸出3.23322
注:Number建構函式將字串轉換為數字時,字串必須完全被為數字,即只要有一個字元無法轉為數值,則整個字串都會被轉為NaN。如果想不精確轉換,可以使用parseInt()函式,parseInt()函式將最大限度的將字串轉換為數字。如:
console.log(parseInt('123abc456'));//123
console.log(Number('123abc456'));//NaN
物件型別轉換為數字,和上面物件轉換為字串類似,只是轉為數字時是先呼叫valueOf()方法,再呼叫tostring()方法:
1、首先呼叫物件自身的valueOf()方法,如果返回基本型別的值,則用Number建構函式進行轉換。
2、如果valueOf()返回的不是基本型別的值,則再呼叫toString()方法,如果返回基本型別的值,值用Number建構函式進行轉換。
3、如果toString()返回的不是基本型別的值,則丟擲異常。
驗證方法與上面轉為字串的類似,如:
var obj={
valueOf:function(){
console.log('執行了valueOf()方法,這裡返回數字2');
return 2;
},
toString:function(){
console.log('執行了toString(),這裡返回物件');
return 1;
}
};
Number(obj);
輸出結果:
執行了valueOf()方法,這裡返回數字2
2.3、將其他型別轉換為布林值
使用Boolean建構函式轉換其他型別的數值時,除了下面幾種情況返回false外,其他的值都返回true。1、null
2、0、-0或者+0
3、NaN
4、'' 空字串
5、undefined
如:
console.log(Boolean(null));//false
console.log(Boolean(0));//false
console.log(Boolean(-0));//false
console.log(Boolean(+0));//false
console.log(Boolean(''));//false
console.log(Boolean(NaN));//false
console.log(Boolean(undefined));//false
console.log(Boolean({}));//true
console.log(Boolean([]));//true
console.log(Boolean("蟈蟈"));//true
console.log(Boolean(new Boolean(false)));//true
三、自動(隱性)型別轉換
自動型別轉換就是不需要人為強制的進行轉換,js會自動將型別轉換為需要的型別,所以該轉換操作使用者是感覺不到的,因此又稱為隱性型別轉換。自動型別轉換實際上和強制型別轉換一樣,也是通過String()、Number()、Boolean()等建構函式進行轉換,只是該操作是JS自己自動完成的而已。自動型別轉換的規則和強制型別轉換的規則一致,所以這裡不再進行描述。下面列舉幾個例子:
3.1、轉換為數字
在所有加減乘除等需要數字型別的地方,JS會自動使用Number建構函式對變數進行轉換。
console.log('1'-'2');//-1
console.log(1+'2');//12 加號+比較特殊,其他型別和字串相加都會轉換成字串
console.log('1'-true);//0
console.log('1'*{});//NaN
console.log('1'-'a');//NaN
3.2、轉換為字串
字串自動轉換主要表現為字串的拼接,字串和其他型別用加號(+)拼接時,其他型別都自動轉換為字串。console.log('1'+'2');//12
console.log('1'+'a');//1a
console.log('1'+1);//11
console.log('a'+null);//anull
console.log('1'+undefined);//1undefined
console.log('a'+{});//a[object Object]
console.log('a'+true);//atrue
3.3、轉換為布林值
當在任意需要布林型別的地方(如,if條件出、三元運算子條件等),系統都會自動呼叫Boolean()建構函式將值轉換為Boolean型別。null、0、-0、+0、'' 空字串、undefined、NaN這些都會轉換為false,其他的值都會轉換為true。