33 個 JavaScript 核心概念系列(四): == 與 ===

原文地址:落明的博客,轉載請註明出處!java

JavaScript 中的 == 與 ===

1、前言

做爲一個程序員,我想你們在第一次看到 a = b 的語句時必定是懵逼的。後來才知道 = 在編程語言中是用來賦值的,而不是用來判斷兩個值是否相等。git

那該怎麼判斷兩個值是否相等呢?在 C 或 java 中,是使用 == 來進行比較,而 JavaScript 就有意思了,除了使用 == , 還加了 ===程序員

2、區別與選擇

  1. 它們有什麼區別?

    具體的區別就一句話:== 在比較時容許進行強制類型轉換,而 === 不容許。github

    不少人都擔憂 == 作的事情多一些會不會影響比較的速度,說實話,會的,但影響是微秒級別的,徹底能夠忽略不計。編程

    不難看出,== 像是 === 的一種更深刻的擴展,所以,知足 === 的值必定知足 ==,反之則不成立。後端

  2. 該如何選擇使用它們?

    不少人會建議你堅持使用 === 而不使用 ==, 我認爲這是不明智的,有些時候,好比說處理後端返回的數據時,你沒法保證對方傳來的值到你進行比較的時候仍是預期的那樣,此時我以爲徹底在能夠適當的使用 == 來進行兼容。安全

    總的來講,當你真的肯定進行比較的值是類型相同的,那就使用 ===,不然,除了幾種特殊狀況,使用 == 並無什麼問題 。bash

3、=== 的比較規則

  1. 基本類型值的比較

    === 的比較規則很簡單,對於非對象類型的值,先判斷兩邊的操做數是不是同一類型,若是是,則進行比較,不然,直接返回 false編程語言

    但有兩個例外狀況:NaN === NaN+0 === -0ui

    // 不一樣類型
    '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
    複製代碼
  2. 引用類型值的比較

    對於包含引用類型值的比較,仍然會先判斷兩邊的數據類型,若是隻有一個是引用類型值,則直接返回 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
    複製代碼

4、== 的比較規則

一開始說過了,在使用 == 進行比較時,運行對兩邊的操做數進行強制類型轉換,那麼問題來了,什麼狀況下會進行轉換?不一樣類型的轉換規則又是怎樣?

MDN 中有這樣一張表,用來展現不一樣類型值進行 == 判斷時的轉換規則。

乍一看可能會以爲很亂,但仍然是能夠分幾種狀況來歸納這些狀況。

在具體分析以前,建議先閱讀上一篇文章 顯式 (名義) 與 隱式 (鴨子)類型轉換 ,由於上圖中你能看到有諸如 isFalsy()ToNumber()ToString()ToPrimitive 等抽象方法,使用它們只是爲了讓你們知道強制轉換的方向和結果,而這些也都是上一篇文章講到的內容。

  1. UndefinedNull 與其它類型值的比較

    咱們看前兩行和前兩列能夠發現:它們只和自身及對方相等,與其餘類型值比較均返回 false ....這個大概就是傳說中的「黑風雙煞」吧!

    你們可能會看到 Object 有一個 isFalse() 方法,這個方法是用來判斷參數值是不是假值,這個時候你們可能會有疑問了,對象不是都是真值嗎?

    沒錯,document.all 就是一個假值對象,雖然已經被新的 JavaScript 標準廢棄,但你或許會在老的項目中看到它,記住就好。

    因爲這倆值的特殊性,後面咱們說「其餘類型」值的時候是排除這倆類型的。

  2. Number 類型值與其餘類型值比較

    除了上面的黑風雙煞,Number 算是相等比較時的大哥,誰想和它比較,就得先轉成 Number 類型。

  3. Boolean 類型值與其餘類型值比較

    既然有大哥,確定得有小弟,而 Boolean 類型值則身先士卒,以身做則,將大哥的原則貫徹到底,堪稱模範小弟!

    其餘類型值想和 Boolean 值作比較,Boolean 值搖身一變將本身轉成了 Number 類型,哎,你說,別人能怎麼辦?!

    不管別人怎麼說,Boolean 只想作一隻安靜的舔狗,無怨無悔,一輩子一世。

  4. Object 類型值與其餘類型值比較

    Object 做爲 JavaScript 中最會假裝本身的一種類型,在比較以前誰也摸不透它們的真實身份。也正由於此,它們的日子過得不盡相同。

    在進行比較時,JavaScript 國王會經過 toPrimitive() 方法來揭開他們的真面目,最終你會發現,它們的真實身份多是任意的一種基本類型。

    所以,在最終比較時,它們也將以真實身份與其餘類型值比較。

  5. String 類型值與其餘類型值比較

    對於 String 類型值來講,在進行比較時的日子並很差過,畢竟,黑風雙煞惹不起,黑社會說話也得聽,惟一能讓它感覺到生活但願的,就是在與 Object 這個變色龍進行比較的時候了。

    只有 ObjecttoPrimitive() 後轉爲字符串的時候它們能夠以字符串的規則進行比較,不然,它們就要面臨黑風雙煞或是黑社會。

5、== 正確的使用方法

github 上有位大神總結了下面這張圖:

咱們能夠將此當作一份參考。

其實在實際的使用過程當中,只要咱們避免一些特殊的狀況,== 的使用仍是安全的。

下面就是七種所謂的特殊狀況。

"0" == false; // true -- 暈!
false == 0; // true -- 暈!
false == ""; // true -- 暈!
false == []; // true -- 暈!
"" == 0; // true -- 暈!
"" == []; // true -- 暈!
0 == []; // true -- 暈!
複製代碼

如何避免?兩個原則:

  1. 若是兩邊的值中有 true 或者 false,千萬不要使用 ==。
  2. 若是兩邊的值中有 []、"" 或者 0,儘可能不要使用 ==。

6、最後

檢驗你們成果的時候到了,

  1. 仔細想一想上面七種特殊狀況的產生緣由。
  2. 思考下面這些值的比較結果。
[] == ![]; // ?
2 == [2]; // ?
'' == [null] // ?

Number.prototype.valueOf = function() {
 return 3;
};
new Number( 2 ) == 3; // ?

複製代碼
相關文章
相關標籤/搜索