JS真是博大精深啊,看似相等,其實不等,而看似不等,卻是相等。
沒錯,你沒有看錯,JS就是這麼不可思議!
這個問題涉及到JS基礎,通常會出現在前端面試題中,剛開始我對于此問題也是存在疑惑的,但隻要明白其原理也很好了解。
一、[]==[]為false
在JS中,數組是屬于引用型資料類型,是以“==”左右兩邊所表示的實際隻是數組的所在的位址而已。在建立一個新數組時,其位址均不相同,是以[]==[]最終傳回false。
二、[]==![]為true
這個就有點難了解了,按照正常思維來看,符号“!”代表的是取反,是以“==”兩邊的值應該不等才是。
這個就涉及到了JS中的資料類型轉換的問題,當我們使用“==”來對資料進行比較時,若兩個資料類型不一緻,JS會先按照一定規則将資料轉換為同一資料類型後再進行比較。
1. 若其中一個資料類型為數值,那麼另一個資料類型會先轉換成數值然後再與之比較
① 字元串與數值
console.log(""==1); // false
console.log(""==0); // true
console.log("hello"==1); // false
console.log("000"==0); // true
console.log("666"==666); // true
需要注意的是,
"hello"
轉換為數字是
NaN
。
② 布爾值與數值
console.log(true==1); // true
console.log(true==2); // false
console.log(false==0); // true
很簡單,
true
被轉換為
1
,
false
③ 數組與數值
console.log([]==0); // true
console.log([1]==1); // true
console.log(["1"]==1); // true
console.log([1,2]==1); // false
console.log([true]==1); // false
需要注意的是,數組會先通過調用
toString()
轉換為字元串後再轉換為數值,比如
[true]
轉換為字元串後為
"true"
,然後再轉換為數值是
NaN
,是以
[true]==1
傳回
false
事實上,數組、對象和函數在與其他基本資料類型進行比較時都會先轉換為字元串,然後再轉換為相應的資料類型(這裡指的資料類型也可能需要轉換,總之最後比較時一定是同一資料類型)進行比較,在此就不再一一舉例了。
④ null、undefined和NaN
這三個是個特例,他們比較特殊:
a) null==undefined為true;
b) null和undefined不會進行資料轉換;
c) NaN不與任何值相等,甚至包括它自己!
我們來看幾個例子:
console.log(null==undefined); // true
console.log(null==0); // false
console.log(null==false); // false
console.log(null==""); // false
console.log(undefined==0); // false
console.log(undefined==false); // false
console.log(undefined==""); // false
console.log(undefined==NaN); // false
console.log(null==NaN); // false
console.log(NaN==NaN); // false
2. 若其中一個資料類型為布爾值,則會先将其轉換成數值再進行比較
console.log(true=="001"); // true
console.log(true==[]); // false
console.log(true==["true"]); // false
console.log(true==[true]); // false
console.log(true==[1]); // true
剛開始接觸若不知道其原理,這些其實都很容易判斷錯誤,但知道轉換規則之後也比較好判斷。
我們可以看到,
==
左側均為
true
,而右側均不是布爾值類型,是以不管三七二十一,先将
true
轉換成數值
1
,然後再根據上面 1 中所講與數值類型比較的轉換規則,将右側值統統進行資料類型轉換,轉換後如下所示:
console.log(1==1); // true
console.log(1==0); // false
console.log(1==NaN); // false
console.log(1==NaN); // false
console.log(1==1); // true
3. “!” 為邏輯非,在操作非布爾值類型的資料時,會将該資料類型先轉換為布爾值後再取反
console.log(!""); // true
console.log(!"false"); // false
console.log(!2); // false
console.log(![]); // false
console.log(!["false"]); // false
console.log(!NaN); // true
關于其他資料類型轉布爾值,以下均傳回true:
① 非空字元串
② 非零數值
③ 數組
④ 對象
⑤ 函數
了解了以上資料類型轉換規則之後在來了解
[]==![]
的問題就很簡單了:
① 将右側數組轉換為布爾值後再取反,轉換後相當于
==
② 根據“比較前布爾值轉數值”規則,轉換後相當于
[]==false
③ 根據“比較前數組遇數值先轉字元串後轉數值”規則,轉換後相當于
[]==0
0==0
本文重點總結
① 相等操作符,不同資料類型會根據一定規則轉換為同一資料類型再比較
② 數組與數組比較,比較的是其引用
③ 不同類型比較,遇數值則轉數值,布爾值自身轉數值
④ 非空非零引用型,轉為布爾均為真