严格的相等运算符将告诉您两个对象 types 是否相等 . 但是,有没有办法判断两个对象是否相等,Java中的值是多少?
Stack Overflow问题Is there any kind of hashCode function in JavaScript?与此问题类似,但需要更多学术答案 . 上面的场景说明了为什么有必要有一个,我想知道是否有任何 equivalent solution .
严格的相等运算符将告诉您两个对象 types 是否相等 . 但是,有没有办法判断两个对象是否相等,Java中的值是多少?
Stack Overflow问题Is there any kind of hashCode function in JavaScript?与此问题类似,但需要更多学术答案 . 上面的场景说明了为什么有必要有一个,我想知道是否有任何 equivalent solution .
30 回答
这是stringify技巧的一个版本,它可以减少输入,并且可以在很多情况下进行简单的JSON数据比较 .
只是想利用一些es6功能贡献我的对象版本比较 . 它不会考虑订单 . 将所有if / else的转换为三元后,我带来了以下内容:
你是否试图测试两个物体是否相等?即:他们的 property 是平等的?
如果是这种情况,您可能已经注意到这种情况:
你可能需要这样做:
显然,该函数可以进行相当多的优化,并且能够进行深度检查(处理嵌套对象:
var a = { foo : { fu : "bar" } }
)但是你明白了 .正如FOR指出的那样,您可能必须根据自己的目的进行调整,例如:不同的类可能有不同的"equal"定义 . 如果您只是使用普通对象,上面的内容就足够了,否则自定义
MyClass.equals()
功能可能就好了 .我遇到了同样的问题,并决定编写自己的解决方案 . 但是因为我想比较Arrays和Objects,反之亦然,我制作了一个通用的解决方案 . 我决定将这些函数添加到原型中,但可以轻松地将它们重写为独立函数 . 这是代码:
该算法分为两部分; equals函数本身和一个函数,用于查找数组/对象中属性的数字索引 . 只需要查找函数,因为indexof只查找数字和字符串而没有对象 .
人们可以这样称呼它:
该函数返回true或false,在这种情况下为true . 算法允许比较非常复杂的对象:
上面的示例将返回true,即使属性具有不同的顺序 . 需要注意的一个小细节:此代码还检查相同类型的两个变量,因此“3”与3不同 .
这是上述所有内容的补充,而不是替代品 . 如果你需要快速浅比较对象而不需要检查额外的递归情况 . 这是一个镜头 .
这比较:1)自有属性数量的平等,2)密钥名称的相等性,3)如果bCompareValues == true,相应属性值的等价及其类型(三重相等)
对于这个有一个非常简单的修复,当你比较两个对象时,你所要做的就是两个对象上的JSON.stringify() .
JavaScript for Objects中的默认相等运算符在引用内存中的相同位置时产生true .
如果您需要一个不同的相等运算符,则需要在类中添加
equals(other)
方法或类似的方法,并且问题域的具体内容将确定这意味着什么 .这是一个扑克牌示例:
如果你有一个深度复制功能,你可以使用以下技巧仍然使用
JSON.stringify
匹配属性的顺序:演示:http://jsfiddle.net/CU3vb/3/
理由:
由于
obj1
的属性将逐个复制到克隆,因此将保留它们在克隆中的顺序 . 当obj2
的属性被复制到克隆时,由于obj1
中已存在的属性将被覆盖,因此将保留其在克隆中的顺序 .Simplest 和 logical 用于比较所有内容的解决方案,如 Object, Array, String, Int...
JSON.stringify({a: val1}) === JSON.stringify({a: val2})
注意:
您需要将Object替换为
val1
和val2
对于对象,您必须递归(按键)对两个侧对象进行排序
为了比较简单键/值对对象实例的键,我使用:
一旦比较了密钥,一个简单的附加循环就足够了 .
复杂度是O(N * N),N是键的数量 .
我希望/猜测我定义的对象不会超过1000个属性......
这是我的版本 . 它正在使用ES5中引入的新Object.keys功能以及+,+和+中的构思/测试:
如果您在AngularJS中工作,
angular.equals
函数将确定两个对象是否相等 . 在Ember.js中使用isEqual
.angular.equals
- 有关此方法的更多信息,请参阅docs或source . 它也对数组进行了深入的比较 .Ember.js
isEqual
- 有关此方法的更多信息,请参阅docs或source . 它没有对数组进行深入比较 .如果您使用的是JSON库,则可以将每个对象编码为JSON,然后比较生成的字符串是否相等 .
NOTE: While this answer will work in many cases, as several people have pointed out in the comments it's problematic for a variety of reasons. In pretty much all cases you'll want to find a more robust solution.
许多人都没有意识到这个问题的简单解决方案是对JSON字符串进行排序(每个字符) . 这通常也比这里提到的其他解决方案更快:
关于此方法的另一个有用的事情是您可以通过将"replacer"函数传递给JSON.stringify函数(https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify#Example_of_using_replacer_parameter)来过滤比较 . 以下内容仅比较名为"derp"的所有对象键:
Heres是ES6 / ES2015中使用功能风格方法的解决方案:
demo available here
功能短
deepEqual
实施:Edit :版本2,使用jib的建议和ES6箭头功能:
需要一个比发布的更通用的对象比较功能,我做了以下工作 . 批评赞赏......
如果您通过Babel或其他方式使用ES6+,您也可以使用
Object.is(x, y)
.参考:http://wiki.ecmascript.org/doku.php?id=harmony:egal#object.is_x_y
我建议不要使用散列或序列化(如JSON解决方案所示) . 如果你需要测试两个对象是否相等,那么你需要定义equals的含义 . 可能是两个对象中的所有数据成员都匹配,或者可能是内存位置必须匹配(意味着两个变量都引用内存中的同一对象),或者可能是每个对象中只有一个数据成员必须匹配 .
最近我开发了一个对象,每次创建一个实例时,它的构造函数都会创建一个新的id(从1开始并递增1) . 该对象有一个isEqual函数,用于将该id值与另一个对象的id值进行比较,如果匹配则返回true .
在那种情况下,我将“相等”定义为id值匹配 . 鉴于每个实例都具有唯一ID,这可以用于强制匹配对象也占据相同内存位置的想法 . 虽然没有必要 .
我用这个函数做了以下假设:
您可以控制要比较的对象,并且只有原始值(即不是嵌套对象,函数等) .
您的浏览器支持Object.keys .
这应该被视为一个简单策略的示范 .
如果您要比较JSON对象,可以使用https://github.com/mirek/node-rus-diff
用法:
如果两个对象不同,则返回与MongoDB兼容的
{$rename:{...}, $unset:{...}, $set:{...}}
like对象 .在Node.js中,您可以使用其原生
require("assert").deepEqual
. 更多信息:http://nodejs.org/api/assert.html例如:
另一个返回
true
/false
而不是返回错误的示例:我使用这个
comparable
函数来生成JSON可比对象的副本:在测试中派上用场(大多数测试框架都有
is
函数) . 例如 .如果捕获到差异,则会记录字符串,从而产生差异:
如果两个对象对所有属性具有相同的值并且对所有嵌套对象和数组递归,则认为两个对象相等是有用的 . 我还认为以下两个对象是相同的:
类似地,数组可以具有“缺失”元素和未定义元素 . 我会同样对待那些:
实现此相等定义的函数:
Source code(包括辅助函数,generalType和uniqueArray):Unit Test和Test Runner here .
你可以使用underscore.js库中的
_.isEqual(obj1, obj2)
.这是一个例子:
请参阅此处的官方文档:http://underscorejs.org/#isEqual
从我的个人图书馆退出,我反复使用这个图书馆 . 以下函数是一个宽泛的递归深度相等,其中 does not check
类平等
继承的值
值严格平等
我主要用它来检查我是否得到了针对各种API实现的平等回复 . 可能发生实现差异(如字符串与数字)和其他空值 .
它的实现非常简单和简短(如果所有注释都被删除)
The short answer
简单的答案是:不,没有通用的方法来确定一个对象在你的意思上是否与另一个对象相等 . 例外情况是您严格考虑对象是无类型的 .
The long answer
概念是Equals方法,它比较对象的两个不同实例,以指示它们在值级别上是否相等 . 但是,由特定类型决定如何实现
Equals
方法 . 具有原始值的属性的迭代比较可能是不够的,可能存在不被视为对象值的一部分的属性 . 例如,在上面的例子中,
c
对于确定MyClass的任何两个实例是否相等并不重要,只有a
和b
是重要的 . 在某些情况下,c
可能会因实例而异,但在比较期间并不显着 .请注意,当成员本身也可以是类型的实例时,此问题适用这些都需要有一个确定平等的手段 .
更复杂的是,在JavaScript中,数据和方法之间的区别是模糊的 .
对象可以引用一个被称为事件处理程序的方法,这可能不会被视为其“值状态”的一部分 . 而另一个对象可能被赋予执行重要计算的功能,从而使该实例与其他实例不同,仅仅因为它引用了不同的功能 .
如果某个对象的某个现有原型方法被另一个函数覆盖了?是否仍然可以认为它与另一个实例相同?这个问题只能针对每种类型在每种特定情况下得到解答 .
如前所述,异常将是严格无类型的对象 . 在这种情况下,唯一合理的选择是每个成员的迭代和递归比较 . 即使这样,人们也要问一个函数的“ Value ”是什么?
我不知道是否有人发布了与此相似的内容,但这是我为检查对象平等而做的功能 .
此外,它是递归的,所以它也可以检查深度相等,如果这就是你所说的 .
为什么重新发明轮子?试试Lodash . 它有许多必备功能,例如isEqual() .
它将强制检查每个键值 - 就像本页上的其他示例一样 - 使用ECMAScript 5和本机优化(如果它们在浏览器中可用) .
注意:以前这个答案建议使用Underscore.js,但是lodash在修复错误和解决一致性问题方面做得更好 .
我知道这有点旧,但我想为这个问题添加一个我想出的解决方案 . 我有一个对象,我想知道它的数据何时发生了变化 . “类似于Object.observe的东西”,我做的是:
这里可以复制并创建另一组数组来比较值和键 . 它非常简单,因为它们现在是数组,如果对象具有不同的大小,则返回false .