為什麼 [] == ![] 為 true?

林恒發表於2024-07-02

🧑‍💻 寫在開頭

點贊 + 收藏 === 學會🤣🤣🤣

前言

面試官問我,[] == ![] 的結果是啥,我:蒙一個true; 面試官:你是對的;我:內心非常高興; 面試官:解釋一下為什麼; 我:一定要冷靜,要不就說不會吧;這個時候,面試官笑了,同學,感覺你很慌的一批啊!

不必慌張,我們慢慢來! 在當今的程式設計領域,面試不僅是技術能力的考察,更是思維靈活性與深度理解的試金石。面試中偶遇諸如 [] == ![] 表示式這類題目,雖讓人初感意外,實則深藏玄機,考驗著我們對於JavaScript這類動態語言特性的透徹理解。這類問題觸及了型別轉換、邏輯運算以及語言設計的微妙之處,促使我們跳出日常編碼的舒適區,深入探索程式語言的底層機制。接下來,我們將一步步揭開這道題目的神秘面紗,不僅為解答此類問題提供思路,更旨在透過這一過程,提升我們對JavaScript核心概念的掌握與應用能力。

首先我們來聊一下基礎的東西。

1.原始值轉布林

首先是原始值轉布林

console.log(Boolean(1));//true
console.log(Boolean(0));//false
console.log(Boolean(-1));//true
console.log(Boolean(NaN));//false
console.log(Boolean('abc'));//true
console.log(Boolean(''));//false
console.log(Boolean(false));//flase
console.log(Boolean(undefined));//false
console.log(Boolean(null));//false

2.原始值轉數字

console.log(Number('123'));//123
console.log(Number('hello'));//NaN
console.log(Number(true));//1
console.log(Number(false));//0
console.log(Number(''));//0
console.log(Number(' '));//0
console.log(Number(undefined));//NaN
console.log(Number(null));//0

3.原始值轉字串

console.log(String(123));//'123'
console.log(String(true));//'true'
console.log(String(false));//'false'
console.log(String(undefined));//'undefined'
console.log(String(null));//'null'

然後我們來了解一下與物件有關的轉換邏輯

4. 原始值轉物件

let a = new Number(1)
console.log(a);//[Number: 1]

其實也沒有很特殊的,就是利用建構函式去進行顯式轉換即可。

5.物件轉原始值

5.1 物件轉布林

首先我們來到這題,最後結果會被列印,說明物件在轉換為布林值的時候,不管什麼物件,都是被轉換為true。

5.2 + 一元運算子

我們先來了解一下,一元運算子的作用。查閱js官方文件,我們可以知道就是呼叫ToNumber()得到結果。而ToNumber()就是呼叫Number方式所呼叫的內建函式,因此就是強制轉換為數字。我們也可以理解為+和Number()的作用是一樣的。

5.3 + 二元運算子

二元運算子呼叫ToPrimitive()方法(ToNumber中的,轉換方式有差異)。

5.4 ToNumber()方法

那麼這個方法具體執行過程是什麼呢?我們可以看到,如果是基本資料型別轉數字,我們之前已經聊到,因此不必多聊,而面對物件轉數字的時候,我們會先呼叫ToPrimitive方法。

5.5 ToPrimitive()方法

關於這個方法,我們要看是被ToNumber還是Totring方法給呼叫了。二者在返回值的順序上會有所差異。 我們來聊一聊裡面的valueOf()和toString()方法。

5.6 toString()和valueOf()方法

1. {}.toString() 得到由"[object class ] "組成字串
2. [].toString() 返回由陣列內部元素以逗號拼接的字串
3. xx.toString() 返回字串字面量

- valueOf 也可以將物件轉成原始型別
1. 包裝類物件

5.6 == 比較

我們首先引入官方文件

首先我們看二者型別相同時的比較, 裡面有一點需要注意,只要有一個NaN就返回false,其他的我們應該都清楚。

二者型別不相等時,我們需要特別注意的是,null和undefined是相等的,字串和數字則把字串轉數字,布林和其他把布林轉數字,出現物件先把物件轉原始值。

估計上面的大量乾貨已經把大家快搞懵逼了,此這裡我們做個簡單小結,這裡面的方法前面都有提到哦。

5.7 小結(重點)

物件轉數字

Number(obj) => ToNumber(obj) => ToNumber(ToPrimitive(obj,Number))

物件轉字串

String(obj) => ToString(obj) => ToString(ToPrimitive(obj,String))

5.8 大量實戰練習

這一題我們知道+的作用和Number的方法是一樣的。因此是轉換為數字123.

那麼這一題,我們考慮到

Number([]) => ToNumber([]) => ToNumber(ToPrimitive([], Number))=> ToNumber('') => 0

這裡只要物件轉布林均為true

這裡的底層原理(5.3裡說了)是,我們首先兩邊都呼叫ToPrimitive方法,看看有沒有字串,有的話就把另一方轉換為字串,沒有的話就全部呼叫ToNumber方法相加。

這裡也是一樣的原理。

我們先把兩邊轉換為原始值,左邊為' ',右邊為'[object object]',發現存在字串,因此相加。

這裡只要我們看5.6就可以很輕鬆搞懂。

同上一個。

首先有物件,我們把物件轉原始值,然後為NaN,為false.

最後回到我們最開始的題目,首先碰見![],我們先把[]轉為布林,為true,!true為false,然後把左邊物件轉原始值,為' ' == false,出現布林和字串,把布林轉數字,為' ' == 0,出現字串和數字,把字串轉數字,為0 == 0,因此最後結果為true

如果對您有所幫助,歡迎您點個關注,我會定時更新技術文件,大家一起討論學習,一起進步。

為什麼 [] == ![] 為 true?

相關文章