前言
JavaScript中型別轉換是一個非常重要的概念,因為JavaScript是一種弱型別或者說動態型別語言,這意味著變數的型別可以在執行時改變。這為開發提供了靈活性,但也可能導致意外的型別轉換行為。
原始值轉原始值——顯示型別轉換
通常我們主觀使用的轉換方式為顯示型別轉換如,在講解轉換前我們先宣告幾個資料型別:
let s='s' let n=123 let f=false let u=undefined let un=null
Boolean()- 轉換為布林值
Boolean()
是JavaScript的一個內建建構函式,主要用於將給定的值轉換為布林型別。在JavaScript中,布林型別只有兩個值:true
和 false
。
字串轉布林型別
console.log(Boolean(s));//true console.log(Boolean(''));//false
在字串型別中,只有空字串在轉換後會被判定為false,其餘的全部會判定為true
數字型別轉布林型別
console.log(Boolean(n));//true console.log(Boolean(0));//false console.log(Boolean(-1));//true console.log(Boolean(Infinity));//true console.log(Boolean(-Infinity));//true console.log(Boolean(NaN));//false
在數字型別中,只有0和NaN轉換後會被判定為false,其餘的全部會判定為true
Number()- 轉換為數字
字串型別轉數字型別
console.log(Number('123'))//123 console.log(Number('abc'))//NaN console.log(Number(''))//0 console.log(Number(' '))//0 console.log(Number('a123'))//NaN console.log(Number('0x00'))//0 十六進制 console.log(Number('0o75')); //61 八進制
當字串中的字元完全是數字字元時,將自動轉為對應的數字,而當嘗試將包含非數字字元的字串(如'abc')轉換為數字時,結果是NaN(Not-a-Number),表示該值不能表示一個合法的數字。空字串和一個只包含空格的字串在轉換為數字時被解釋為0,因為沒有提供任何數值資訊。 字串'0o'或者是以'0x'開頭的,這在JavaScript中是八進制數和十六進制數的標準字首。當在進行型別轉換時,由於數字型別預設為十進制數,檢索到'0o'或者是以'0x'開頭的字元在符合轉換的前提下將被轉換為10進位制,否則轉換為NaN
其他原始型別轉數字型別
console.log(Number(true))//1 console.log(Number(false))//0 console.log(Number(undefined))//NaN console.log(Number(null))//0 console.log(Number())//0
對於布林型別的值轉為數字型別true
轉為1,false
轉為0。因為undefined
表示變數未被賦值,它沒有一個具體的數值,因此無法轉換成一個有意義的數字。而當嘗試將null
轉換為數字時,結果是0
。而在JavaScript中,當Number()
函式沒有被傳遞任何值或者傳遞的是undefined
時,它會返回0
。至於為什麼可以查閱es5官方文件Annotated ES5
String()- 轉換為字串
console.log(String(n));//123 console.log(String(0));//0 console.log(String(-1));//-1 console.log(String(Infinity));//Infinity console.log(String(-Infinity));//-Infinity console.log(String(NaN));//NaN console.log(String(undefined));//undefined console.log(String(null));//null
我們可以看到,當使用String()
函式時,它不會改變原始值的型別;它只是返回一個表示原始值的字串形式。這意味著原始值(如數字、null
、undefined
等)本身的型別和值並未改變
物件轉原始值——隱式型別轉換
隱式型別轉換中,主要探究的就是物件為主的引用資料型別。
引用資料型別- 轉Number:Number( { } )
在轉換之前,我們要弄清楚Number()函式的執行原理是什麼,Number()函式會在一開始先呼叫內部函式ToNumber(x)
可以看到ToNumber(x)該函式中會呼叫ToPrimitive()將物件轉為原始值,開啟ToPrimitive()的解釋
我們可以看到對於ToNumber(x)中的ToPrimitive(Object,Number)的執行步驟為:
1.判斷接收到的值是不是原始型別,是則返回;
2.呼叫valueOf()方法,如果得到了原始值則返回
3.呼叫toString方法,如果得到了原始值則返回
4.報錯
例項
console.log(Number({}))//NaN console.log(Number([]))//0 console.log(Number([1]))//1 console.log(Number([1,2]))//NaN
在這幾個例子中,都是進行到第三步呼叫toString方法後返回值變String型別然後對其進行Number()型別轉化。
引用資料型別- 轉String:String( { } )
同樣的在轉換之前,我們要弄清楚String()函式的執行原理是什麼,String()函式會在一開始先呼叫內部函式ToString(x)
可以看到ToString(x)該函式中會呼叫ToPrimitive()將物件轉為原始值。因此我們可以看到對於ToString(x)中的ToPrimitive(Object,String)的執行步驟為:
1.判斷接收到的值是不是原始型別,是則返回;
2.呼叫toString方法,如果得到了原始值則返回
3.呼叫valueOf()方法,如果得到了原始值則返回
4.報錯
例項
console.log(String({}))//[object Object] console.log(String([]))//'' 空字串 console.log(String([1]))//'1' console.log(String([1,2]))//'1,2'
為什麼ToString(x)中的ToPrimitive()會將toString方法放在前面呢,詳細想想,toString對所有原始資料型別都能強制轉換,就也不需要valueOf()判斷了。
引用資料型別- 轉Boolean:Boolean( { } )
任何物件轉Boolean都是true,這就不用過多敘述了,看個例子:
console.log(Boolean({}));//true
總結
在ToPrimitive()中的toString方法不是內部方法,而是使用轉換目標型別的原型鏈上的方法
一元運算子 +
會觸發隱式型別轉換,往Number轉
console.log(+'1'); console.log(+'abc'); console.log(+null); console.log(+undefined); console.log(+true); console.log(+false);
二元運算子 +
優先順序:字串>數字
console.log(1+'1'); console.log("1"+1); console.log("1"+true); console.log("1"+null); console.log("1"+undefined); console.log(1+true); console.log(1+null); console.log(1+undefined);
== vs === 的底層機制
== 會觸發隱式型別轉換而 === 不會觸發,這也是為什麼[] == ![]
為true的原因。
[] == ![], [] == !true, [] ==false, [] == 0 Number([]) == 0 '' == 0 0 == 0