在JavaScript中何時使用==是正確的?

轉載:http://www.cnblogs.com/yanhaijing/p/3685290.htmlhtml

JavaScript中什麼狀況下使用==是正確的?簡而言之:沒有。這篇文章來看五種狀況下老是使用===,而且解釋爲何不用==。瀏覽器

JavaScript有兩種操做符用來比較兩個值是否相等 [1]服務器

  • 嚴格相等 === 僅考慮相同類型的值是否相等。
  • 「正常」(或非嚴格)相等操做符 == 在比較以前,嘗試爲不一樣類型的值進行轉換,而後相似嚴格相等。

給JavaScript初學者的建議是徹底忘掉 == ,而且老是使用 ===。事實證實,後者是更符合常規的。有五種案例,表面看起來能夠不聽從規則,但真的不是這樣。從如今開始,我使用下面的規則:函數

意圖清晰的代碼賽過更簡潔的代碼。

記住:你的代碼僅寫一次,但被閱讀不少次——儘量保證對閱讀者友好。性能

例1:你清楚本身在比較什麼

例如,使用typeof操做符[2],你能確保結果是字符串。而後能夠放心使用 ==,由於咱們肯定不會在發生類型轉換。學習

if (typeof x == "function") {
        ...
}

然而,有兩個反對這樣作的緣由:編碼

  • 一致性:使用==對一致性沒有任何好處,那麼爲何不避免使用呢?
  • 簡單和性能:通常來講,=== 是最簡單的操做符,由於它不進行類型轉換。JavaScript引擎的性能良莠不齊[3],但在大部分瀏覽器中 === 比 == 速度更快。

例2:與undefined和null作比較

當使用 == 時,undefined和null在結果上等價——他們彼此相等,互相相等,但沒有意義(包括JavaScript中的能被轉換爲false的值):spa

複製代碼
    > null == null
    true
    > undefined == null
    true
    > false == null
    false
    > 0 == null
    false
複製代碼

所以,下面的if語句檢測的是null或undefined。code

    if (x == null) {
        ...
    }

然而,這是否出於簡潔性考慮,意圖並不清晰:若是你同時也檢測undefined,那麼你能夠這樣寫。然而,若是JavaScript初學者讀到你的代碼,他們可能認爲你僅僅檢測null。若是高手讀到你的代碼,他們可能認爲你寫錯了,而且應該寫成 ===。htm

    if (x === undefined || x === null) {
        ...
    }

若是你有點懶的話,上面的代碼能被精簡爲:

    if (!x) {
        ...
    }

和上面同樣的警告:這條件成立,若是x有否認類型的值。

    undefined
    null
    false
    0
    ""

例3:比較字符串和數字

場景:你正工做在用戶界面代碼或編碼處理服務器端參數。你可能會把數字編碼爲字符串。若是x是一個字符串,你能夠像下面這樣比較:

    if (x == 123) {
        ...
    }

但問什麼不告訴其餘閱讀你代碼的人,若是x不是數字,它將被轉換爲數字?

    if (Number(x) === 123) {
        ...
    }

例4:比較對象和原始值

使用 == 時你能夠將一個原始值和其餘原始值或包裝類型 [4]實例作比較:

    > function isAbc(x) { return x == "abc" }
    > isAbc("abc")
    true
    > isAbc(new String("abc"))
    true

而使用 === 時,你不能這樣作:

    > new String("abc") === "abc"
    false

 左邊是一個對象而右邊是原始值。由於他們類型不一樣因此不嚴格相等。然而,你一樣須要向閱讀你代碼的人解釋清楚你的意圖。下面是表達式:

 x == "abc"

你的目的是什麼?

  • 你真的想讓一個包裝字符串和右邊的字符串做比較嗎?這彷佛不太可能,但若是確實是這樣,你應該當心翼翼並給出文檔記錄。
  • 你想將x轉換爲字符串?那應該寫的更明確
    String(x) === "abc"
  • 你想提取包裝變量的原始值?那你應該考慮下面的寫法
     x.valueOf() === "abc"

例5:JavaScript是靈活的語言——個人代碼也應該這樣

理由是這樣的:我想個人代碼像JavaScript同樣靈活。== 操做符幫我實現這一目的。例如JavaScript的靈活體如今它自動轉換值類型:

    > "abc" + false
    'abcfalse'
    > 3 + true
    4
    > +"73"
    73

有幾個理由反駁上述假說:

  • 即便會自動轉換但並不老是按你須要的方式轉換。例如:
  • 複製代碼
        > !"false"
        false
        > 7 + "3"
        '73'
        > Number("")
        0
    複製代碼
  • 非嚴格相等的轉換規則很是複雜:
        > 2 == false
        false
        > 2 == true
        false
        > Boolean(2)
        true
  • 顯示轉化加上嚴格相等的代碼更具描述性。比較:靈活的非嚴格相等。
    複製代碼
    function is123Implicit(x) {
            return x == 123;
        }
        > is123Implicit(123)
        true
        > is123Implicit(new Number(123))
        true
        > is123Implicit("123")
        true
    複製代碼
    替代方案:靈活的顯式轉換和嚴格相等。
    複製代碼
    function is123Explicit(x) {
            x = Number(x);
            return x === 123;
        }
        > is123Explicit(123)
        true
        > is123Explicit(new Number(123))
        true
        > is123Explicit("123")
        true
    複製代碼

     

  • 有人說您的代碼缺乏靈活性?能夠說JavaScript的默認靈活性利大於弊(對於學習難度而言)。寫防護型的代碼更容易暴漏Bug。is123Explicit() 的防護型版本看起來像下面這樣:
    function is123Defensive(x) {
            if (typeof x !== "number") {
                throw new TypeError("Not a number: "+x);
            }
            return x === 123;
        }
    若是你想給函數傳遞任何非原始數字值,你必須先進行類型轉換。
相關文章
相關標籤/搜索