原文出處: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);
bobaFett
和jangoFett
的屬性徹底相同,可是兩個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);
一方面講,jangoFett
和bobaFett
這兩個變量引用自兩個擁有徹底相同屬性的object,但確實爲兩個不一樣的實例;另外一方面,jangoFett
和callMeJango
指向相同的實例。測試
所以,當你想要驗證對象相等時,你須要清楚你是想要怎麼的相等。若是你是想驗證兩個實例是否完徹底全相同,你可使用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
NaN
(JavaScript中惟一一個自身不相等自身的值)a
有個屬性的值爲undefined
,而b
中沒有這個屬性(所以都等同於undefined
)想要一個檢驗object實例「值相等」的健壯的方法,最好是使用一個涵蓋各類邊界狀況的、通過全面測試的庫。Underscore和Lo-Dash這兩個庫中的_.isEqual
方法對處理object深度比較進行了很好的實現。你能夠這樣使用它們:htm
// Outputs: true console.log(_.isEqual(bobaFett, jangoFett));
但願這個JavaScript的小知識點可以幫助你更好地理解object實例相等的實現原理。