前端面試官必問系列之隱式型別轉換

小明與核桃發表於2020-11-18

什麼是隱式型別轉換?

我們在開發的過程中,很多時候都會用到雙等號 == 進行判斷,以決定接下來執行哪些業務邏輯。

隱式型別轉換:==在比較兩個不同型別的值時會發生隱式型別轉換,會將其中之一或兩者都轉換為相同型別後再進行比較。

那麼轉換的規則是什麼呢?

隱式型別轉換的規則

字串和數字做相等比較,會把字串轉為數字

let a = 10;
let b = '10';
console.log(a == b); //true

有布林值時,會把布林值轉為數值

let a = true;
let b = '1';
console.log(a == b); //true

上述程式碼中,a和b做比較,a會先變為數值1(true對應1,false對應0),然後是數值1和字串1做比較,那麼會應用第一條規則

在==中,null和undefined是相等的

let a = null;
let b;
console.log(a == b);//true

我們觀察上述第一和第二條規則,不難發現,在進行隱式型別轉換時, 雙等號==更加偏愛數值,也就是說,在進行比較時,js會呼叫Number函式把雙等號兩邊的值轉為數值,下面我們來聊聊Number這個內建函式。

Number函式

作用:Number() 函式把物件的值轉換為數值,如果物件的值無法轉換為數值,那麼Number函式則返回NaN。(如果引數是 Date 物件,Number() 返回從 1970 年 1 月 1 日至今的毫秒數)

我們來觀察如下程式碼的輸出:

console.log(Number())
console.log(Number(0))
console.log(Number(''))
console.log(Number('0'))
console.log(Number(false))
console.log(Number(null))
console.log(Number([]))
console.log(Number([0]))

console.log(Number('str'))

上述程式碼中,除了最後一行外,其餘的輸出都為0,而最後一行的輸出是NaN,因為Number()函式無法把字串轉為數值,但是可以把數字型別的字串轉為數值(第四行程式碼)

為了更好地理解我們接下來要給出的面試程式碼題,我們先來討論一下Boolean函式。

Boolean()函式

我們在開發中,或許會寫過如下類似的條件判斷語句:

if (1) {
	console.log('success');
}

上述程式碼會輸出success,因為if的條件為真,原因在於if語句在判斷時,呼叫了Boolean()函式,即Boolean(1) 的值為true。

Boolean函式的作用機制如下:

在js中,除了0,-0,NaN,’"",null,undefined這六個值轉為布林值時,結果為false,其它任何物件轉為布林值,都得到 true。

console.log(Boolean(0));//false
console.log(Boolean(-0));//false
console.log(Boolean(NaN));//false
console.log(Boolean(""));//false
console.log(Boolean(null));//false
console.log(Boolean(undefined));//false

console.log(Boolean([]));//true
console.log(Boolean({}));//true
console.log(Boolean('false'));//true
console.log(Boolean(Date.now()));//true

程式碼輸出題

我們觀察如下程式碼:

if ([] == false) {console.log(1)}
if ({} == false) {console.log(2)}
if ([]) {console.log(3)}
if ([1] == [1]) {console.log(4)}

我們來分析一下上述程式碼。第一第二行程式碼,雙等號兩側會呼叫Number()函式,Number([])=Number(false)=0,所以會輸出1,而Number({})的返回值是NaN,NaN == 0的返回值是false,所以2不會輸出。第三行程式碼會呼叫Boolean()函式,Boolean([])的返回值是true,所以3會輸出。

我們來觀察一下第四行程式碼,乍看之下,好像4一定會輸出,因為雙等號兩側會呼叫Number()函式,而Number([1])=1,1==1返回true,那麼就會輸出4,這樣分析好像沒毛病。然而,上述程式碼不會輸出4。

當雙等號兩邊的值都是引用資料型別(陣列和物件)時,規則不再適用,因為引用資料型別比較的是引用地址,如果兩個值的引用地址是一樣的,那麼它們相等,否則不相等,上述[1] 和 [1]的引用地址不一樣。我們可以用如下規則來判斷引用資料型別:

如果==兩邊的值都是物件,則比較它們是不是同一個物件,如果兩個值都指向同一個物件,則返回 true;否則, 返回false

console.log([] == []);//false
console.log({} == {});//false

let a = {};
let b = a;
//a和b指向同一個物件,所以返回true
console.log(a == b);//true

let c = [];
let d = c;
console.log(c == d);//true

相關文章