原文出处: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实例相等的实现原理。