原文地址:落明的博客,轉載請註明出處!java
做爲一個程序員,我想你們在第一次看到 a = b
的語句時必定是懵逼的。後來才知道 =
在編程語言中是用來賦值的,而不是用來判斷兩個值是否相等。git
那該怎麼判斷兩個值是否相等呢?在 C 或 java 中,是使用 ==
來進行比較,而 JavaScript 就有意思了,除了使用 ==
, 還加了 ===
。程序員
具體的區別就一句話:==
在比較時容許進行強制類型轉換,而 ===
不容許。github
不少人都擔憂 ==
作的事情多一些會不會影響比較的速度,說實話,會的,但影響是微秒級別的,徹底能夠忽略不計。編程
不難看出,==
像是 ===
的一種更深刻的擴展,所以,知足 ===
的值必定知足 ==
,反之則不成立。後端
不少人會建議你堅持使用 ===
而不使用 ==
, 我認爲這是不明智的,有些時候,好比說處理後端返回的數據時,你沒法保證對方傳來的值到你進行比較的時候仍是預期的那樣,此時我以爲徹底在能夠適當的使用 ==
來進行兼容。安全
總的來講,當你真的肯定進行比較的值是類型相同的,那就使用 ===
,不然,除了幾種特殊狀況,使用 ==
並無什麼問題 。bash
===
的比較規則===
的比較規則很簡單,對於非對象類型的值,先判斷兩邊的操做數是不是同一類型,若是是,則進行比較,不然,直接返回 false
。編程語言
但有兩個例外狀況:NaN === NaN
和 +0 === -0
。ui
// 不一樣類型
'12' === 12; // false
'a' === true; // false
null === '12' // false
null === undefined; // false
// 同類型
1 === 1; // true
'a' === 'a'; // true
false === false; // true
null === null; // true
//特殊狀況
NaN === NaN; // false
+0 === -0 // true
複製代碼
對於包含引用類型值的比較,仍然會先判斷兩邊的數據類型,若是隻有一個是引用類型值,則直接返回 false
,若是兩邊均是引用類型值,則會比較他們的引用地址是否一致。
const a = {
m: 'string',
n: 12
};
const b = {
m: 'string',
n: 12
};
const c = 12;
a === b; // false
a === c ; // false
const d = a;
a === d; // true
複製代碼
==
的比較規則一開始說過了,在使用 ==
進行比較時,運行對兩邊的操做數進行強制類型轉換,那麼問題來了,什麼狀況下會進行轉換?不一樣類型的轉換規則又是怎樣?
在 MDN
中有這樣一張表,用來展現不一樣類型值進行 ==
判斷時的轉換規則。
乍一看可能會以爲很亂,但仍然是能夠分幾種狀況來歸納這些狀況。
在具體分析以前,建議先閱讀上一篇文章 顯式 (名義) 與 隱式 (鴨子)類型轉換 ,由於上圖中你能看到有諸如 isFalsy()
、ToNumber()
、ToString()
、ToPrimitive
等抽象方法,使用它們只是爲了讓你們知道強制轉換的方向和結果,而這些也都是上一篇文章講到的內容。
Undefined
和 Null
與其它類型值的比較咱們看前兩行和前兩列能夠發現:它們只和自身及對方相等,與其餘類型值比較均返回 false
。 ....這個大概就是傳說中的「黑風雙煞」吧!
你們可能會看到 Object
有一個 isFalse()
方法,這個方法是用來判斷參數值是不是假值,這個時候你們可能會有疑問了,對象不是都是真值嗎?
沒錯,document.all
就是一個假值對象,雖然已經被新的 JavaScript 標準廢棄,但你或許會在老的項目中看到它,記住就好。
因爲這倆值的特殊性,後面咱們說「其餘類型」值的時候是排除這倆類型的。
Number
類型值與其餘類型值比較除了上面的黑風雙煞,Number
算是相等比較時的大哥,誰想和它比較,就得先轉成 Number
類型。
Boolean
類型值與其餘類型值比較既然有大哥,確定得有小弟,而 Boolean
類型值則身先士卒,以身做則,將大哥的原則貫徹到底,堪稱模範小弟!
其餘類型值想和 Boolean
值作比較,Boolean
值搖身一變將本身轉成了 Number
類型,哎,你說,別人能怎麼辦?!
不管別人怎麼說,Boolean
只想作一隻安靜的舔狗,無怨無悔,一輩子一世。
Object
類型值與其餘類型值比較Object
做爲 JavaScript 中最會假裝本身的一種類型,在比較以前誰也摸不透它們的真實身份。也正由於此,它們的日子過得不盡相同。
在進行比較時,JavaScript 國王會經過 toPrimitive()
方法來揭開他們的真面目,最終你會發現,它們的真實身份多是任意的一種基本類型。
所以,在最終比較時,它們也將以真實身份與其餘類型值比較。
String
類型值與其餘類型值比較對於 String
類型值來講,在進行比較時的日子並很差過,畢竟,黑風雙煞惹不起,黑社會說話也得聽,惟一能讓它感覺到生活但願的,就是在與 Object
這個變色龍進行比較的時候了。
只有 Object
在 toPrimitive()
後轉爲字符串的時候它們能夠以字符串的規則進行比較,不然,它們就要面臨黑風雙煞或是黑社會。
==
正確的使用方法github 上有位大神總結了下面這張圖:
咱們能夠將此當作一份參考。
其實在實際的使用過程當中,只要咱們避免一些特殊的狀況,==
的使用仍是安全的。
下面就是七種所謂的特殊狀況。
"0" == false; // true -- 暈!
false == 0; // true -- 暈!
false == ""; // true -- 暈!
false == []; // true -- 暈!
"" == 0; // true -- 暈!
"" == []; // true -- 暈!
0 == []; // true -- 暈!
複製代碼
如何避免?兩個原則:
檢驗你們成果的時候到了,
[] == ![]; // ?
2 == [2]; // ?
'' == [null] // ?
Number.prototype.valueOf = function() {
return 3;
};
new Number( 2 ) == 3; // ?
複製代碼