[] == ![] ?揭曉你不知道的 ==
theme: smartblue
我正在參加「掘金·啟航計劃」
前言
日常專案開發中,大部分的專案規範會提到使用
===
代替==
,究其原因,無非是相對來講===
的結果是 更可預測 的,相比之下==
伴隨著隱式型別轉換。兩者主要的區別就在於
==
用於檢查 值 是否相等,而===
檢查的是 值與型別 是否相等。別小看這簡單的兩句話,其中伴隨的隱式轉換可不簡單。舉個🌰:
1 == "1"
到底是1
轉換成"1"
還是"1"
轉換成1
呢?
知其所以然
思考🤔
求相等運算子的結果總是返回Boolean
型別,反映運算子所命名的兩個運算元之間的關係是否成立。但,你真的知道 ==
的工作原理嗎?試著看看以下程式碼的執行結果
js
undefined == null; // true
NaN == NaN; // false
1 == "1"; // true
1 == true; // true
2 == true; // false
[] == [] // false
"" == [] // true
0 == [] //true
true == [] // false
true == ![] // false
true == !![] // true
[] == ![] // true
"a" == new String("a"); // true
new String("a") == new String("a"); // false
...
如果你對上面的結果一知半解,或者知道結果但是不知道內部是如何轉換過來的,那麼請繼續往下看
同類型比較(🐕==🐶)
關於 a == b
;假設兩者型別相同:
1、 那麼當 typeof a
為 undefined
,又或者兩者皆為null
,結果為 true;
js
undeinfed == undefined // true
null == null // true
2、 當typeof a
為 string
時,若a、b
是完全相同的字元序列,返回 true;
js
'abc' == 'abc' // true
3、 當typeof a
為 number
時,若 a
或 b
存在1個及以上是 NaN
時,返回 false;否則如果數值相等則為 true,其餘情況為 false;
js
123 == 123 // true
NaN == NaN // false
4、 當typeof a
為 boolean
時,若a、b
都為 true
或都為 false
時,返回 true;否則返回 false;
js
true == true // true
false == false // true
false == true // false
5、 當typeof a
為 object
時,若a、b
指向同一個物件,返回 true;若 a、b
都為 null
返回 true,否則返回 false;
js
{} == {} // false
[] == [] // false,千萬不可使用 xxx == [] 來判斷陣列是否為空
new String("a") == new String("a"); // false
let obj = {}
let a = obj
let b = obj
a == b // true
null == null
不同型別比較(🐖==🐕)(重點)
關於 a == b
;假設兩者型別不相同:
1、a
、b
中有一個是undefined
,另一個是null
時,返回 true
js
undefined == null // true
2、a
、b
中有一個是number
,一個是string
,那麼會將string
轉化為number
再進行比較:
js
1 == '1' // true,轉化成 1 == 1進行比較;'1' == 1 同理
3、 a
或 b
當中存在 boolean
時 ,將 boolean
轉為number
再進行比較:
js
1 == true // true,轉化成 1 == 1進行比較;
'1' == true // true 轉化成 '1' == 1 => 1 == 1
'2' == true // false
'0' == false // true
4、a
或 b
中有一個是object
(非null),且另一個為基本資料型別 ,則先呼叫 object
的valueOf方法,若結果為基本資料型別,則返回結果進行比較;否則呼叫object
的toString方法,若結果為基本資料型別,則返回結果進行比較,否則丟擲錯誤
```js // 優先呼叫valueOf "a" == new String("a"); // true, new String('a').valueOf() === 'a'
let obj = { valueOf(){ return 2 } } 2 == obj // true
// valueOf沒有返回基本型別則呼叫toString let obj1 = { toString(){ return '3' } } 3 == obj1 // true
// toString沒有返回基本型別,報錯 let obj2 = { toString(){ return {} } } 3 == obj2 // 報錯 Cannot convert object to primitive value
0 == [] // true 轉化為 0 == '' => 0 == 0
5、**需要注意的是**,按照上述第四種情況,會出現一些令人意想不到的情況
js
true == [] // false,[] 被轉化成'' => 0
true == ![] // false, 轉化成 true == !true;
true == !![] // true, 轉化成 true == !!true;
// 同理
false == [] // true
false == ![] // true
false == !![] // false
[] == ![] // true 本質上是[] == false; 轉換為 '' == false => 0 == 0 => true
``
這是因為在js中,引用資料型別轉化為
boolean會被轉為true,因此
[]加上
!之後
會先將
[]`轉為 true,再進行取反,結果就為 false 。
===👬
上面提到全等號檢查的是 值與型別,那麼當兩個值型別不同時結果直接為false,若是基本型別且型別相同時則根據自身值是否相同進行判斷。需要注意的是:NaN === NaN
結果是 false。
若兩個值皆為 引用型別,則需要判斷兩者是否指向同一個物件,是則返回 true,否則為 false。
總結
大部分情況下其實使用 ==
都是相對安全的,很多情況下也能簡化我們的程式碼。
容易混淆的主要有以下幾種情況(這些情況下如果不夠明確,那麼考慮使用===
,這對於後續其他開發者來講也是有利的):
- 比較的值裡面有一邊可能是boolean
型別(true/false)
- 比較的值裡面有一邊可能是0
或 ''
或 []
更多時候,如果你能明確知道你寫的程式碼是你想要的結果以及明確其中是怎麼轉換的,那麼==
號就是安全的!否則請儘量避免使用==
,而是使用===
。
相信看到這裡的你已經對其中的轉換規則有了更加深入的理解!
寫得不對或不好的地方歡迎大家指正交流~~