Javascript中的object相等

原文出處:Object Equality in JavaScriptjavascript

相等是JavaScript中起初最讓人困惑的部分。=====的比較、強制類型的順序等等,都使得這個問題變得複雜。今天,咱們會聚焦另外一個方面:object相等是如何實現的。html

你也許認爲,若是兩個object有相同的屬性而且它們多有的屬性值都相同,那麼這兩個object應該是相等的。咱們來看看是否如咱們所料:java

var jangoFett = {
    occupation: "Bounty Hunter",
    genetics: "superb"
};

var bobaFett = {
    occupation: "Bounty Hunter",
    genetics: "superb"
};

// Outputs: false
console.log(bobaFett === jangoFett);

bobaFettjangoFett的屬性徹底相同,可是兩個object並不認爲是相等的。難道是咱們使用恆等運算符的緣由?咱們來驗證下:數組

// Outputs: false
console.log(bobaFett == jangoFett);

咱們這樣作,是由於JavaScript內部其實有兩套不一樣的方案來驗證相等(譯者加:ecma規範中定義的[The Strict Equality Comparison Algorithm
](http://www.ecma-international...)。像字符串以及數值這種基本類型是依據它們的值進行比較的;但像數組、日期以及簡單對象這類object是根據它們的引用進行判斷的。依據引用的判斷會檢查所給的object是否指向內存中的相同地址。下面這個例子會闡述JavaScript中相等運算符的實現原理:ide

var jangoFett = {
    occupation: "Bounty Hunter",
    genetics: "superb"
};

var bobaFett = {
    occupation: "Bounty Hunter",
    genetics: "superb"
};

var callMeJango = jangoFett;

// Outputs: false
console.log(bobaFett === jangoFett);

// Outputs: true
console.log(callMeJango === jangoFett);

一方面講,jangoFettbobaFett這兩個變量引用自兩個擁有徹底相同屬性的object,但確實爲兩個不一樣的實例;另外一方面,jangoFettcallMeJango指向相同的實例。測試

所以,當你想要驗證對象相等時,你須要清楚你是想要怎麼的相等。若是你是想驗證兩個實例是否完徹底全相同,你可使用JavaScript內置的相等運算符;抑或你是想驗證兩個實例擁有「相同的值」,這樣的話,你可能須要多作些工做。ui

如下是檢驗object「值相等」的一種基本實現:this

function isEquivalent(a, b) {
    // Create arrays of property names
    var aProps = Object.getOwnPropertyNames(a);
    var bProps = Object.getOwnPropertyNames(b);

    // If number of properties is different,
    // objects are not equivalent
    if (aProps.length != bProps.length) {
        return false;
    }

    for (var i = 0; i < aProps.length; i++) {
        var propName = aProps[i];

        // If values of same property are not equal,
        // objects are not equivalent
        if (a[propName] !== b[propName]) {
            return false;
        }
    }

    // If we made it this far, objects
    // are considered equivalent
    return true;
}

// Outputs: true
console.log(isEquivalent(bobaFett, jangoFett));

如你所見,想要驗證object實例「值相等」,咱們必須去遍歷object中每一個屬性,看其是否相等。若是咱們把上面實現的這個簡單方案應用在咱們的例子中,不少狀況都是尚未處理的。例如:code

  • 若是某個屬性是一個object
  • 若是某個屬性值時NaN(JavaScript中惟一一個自身不相等自身的值)
  • 若是a有個屬性的值爲undefined,而b中沒有這個屬性(所以都等同於undefined

想要一個檢驗object實例「值相等」的健壯的方法,最好是使用一個涵蓋各類邊界狀況的、通過全面測試的庫。UnderscoreLo-Dash這兩個庫中的_.isEqual方法對處理object深度比較進行了很好的實現。你能夠這樣使用它們:htm

// Outputs: true
console.log(_.isEqual(bobaFett, jangoFett));

但願這個JavaScript的小知識點可以幫助你更好地理解object實例相等的實現原理。

相關文章
相關標籤/搜索