严格相等运算符将告诉您两个对象类型是否相等。然而,是否有一种方法来判断两个对象是否相等,就像Java中的哈希码值一样?
堆栈溢出问题JavaScript中有hashCode函数吗?类似于这个问题,但需要一个更学术的答案。上面的场景说明了为什么有必要有一个,我想知道是否有等效的解决方案。
严格相等运算符将告诉您两个对象类型是否相等。然而,是否有一种方法来判断两个对象是否相等,就像Java中的哈希码值一样?
堆栈溢出问题JavaScript中有hashCode函数吗?类似于这个问题,但需要一个更学术的答案。上面的场景说明了为什么有必要有一个,我想知道是否有等效的解决方案。
当前回答
使用JSON.stringify()并不总是可靠的。所以在我看来,这种方法是你问题的最佳解决方案
首先,不,没有通用的方法来确定一个对象是否相等!
但是有一个概念叫做浅平等比较。 有一个npm库可以帮助你使用这个概念
例子
const shallowequal = require('shallowequal');
const object = { 'user': 'fred' };
const other = { 'user': 'fred' };
// Referential Equality Comparison (`strict ===`)
object === other; // → false
// Shallow Equality Comparison
shallowequal(object, other); // → true
如果你想知道如何创建shallowEqual比较方法,那么请参考这里。它来自开源的fbjs Facebook库。
浅平等比较
shallowequal(其中obj1 methoda)
shallowEqual在两个值(即obj1和obj2)之间进行浅相等比较,以确定它们是否相等。
相等性是通过迭代给定obj1上的键来执行的,并且当任何键的值在obj1和obj2之间不严格相等时返回false。否则,只要所有键的值严格相等,就返回true。
其他回答
纯JS方法:我的答案是基于生成一个返回相同值的字符串,无论属性顺序是否相同。设置对象可用于切换大小写和空白是否重要。(为了避免失去焦点,我没有包括那些支持函数,或者我猜应该在任何实用程序集中的isObject。)
这里也没有显示,但为了减少字符串比较时间,如果对象很大,你想加快比较,你也可以散列字符串和比较子字符串;这只适用于非常大的对象(当然也有很小的机会出现错误的相等)。
然后你可以比较genObjStr(obj1) ?= genObjStr(obj2)
function genObjStr(obj, settings) {
// Generate a string that corresponds to an object guarenteed to be the same str even if
// the object have different ordering. The string would largely be used for comparison purposes
var settings = settings||{};
var doStripWhiteSpace = defTrue(settings.doStripWhiteSpace);
var doSetLowerCase = settings.doSetLowerCase||false;
if(isArray(obj)) {
var vals = [];
for(var i = 0; i < obj.length; ++i) {
vals.push(genObjStr(obj[i], settings));
}
vals = arraySort(vals);
return vals.join(`,`);
} else if(isObject(obj)) {
var keys = Object.keys(obj);
keys = arraySort(keys);
var vals = [];
for(var key of keys) {
var value = obj[key];
value = genObjStr(value, settings);
if(doStripWhiteSpace) {
key = removeWhitespace(key);
var value = removeWhitespace(value);
};
if(doSetLowerCase) {
key = key.toLowerCase();
value = value.toLowerCase();
}
vals.push(value);
}
var str = JSON.stringify({keys: keys, vals: vals});
return str
} else {
if(doStripWhiteSpace) {
obj = removeWhitespace(obj);
};
if(doSetLowerCase) {
obj = obj.toLowerCase();
}
return obj
}
}
var obj1 = {foo: 123, bar: `Test`};
var obj2 = {bar: `Test`, foo: 123};
console.log(genObjStr(obj1) == genObjStr(obj1))
这取决于你对平等的定义。因此,作为类的开发人员,要由您来定义它们的相等性。
有时会使用一种情况,如果两个实例指向内存中的相同位置,则认为它们是“相等的”,但这并不总是您想要的。例如,如果我有一个Person类,如果两个Person对象具有相同的Last Name、First Name和Social Security Number(即使它们指向内存中的不同位置),我可能会认为它们是“相等的”。
另一方面,我们不能简单地说两个对象是相等的,如果它们的每个成员的值都相同,因为,有时,你并不想这样。换句话说,对于每个类,由类开发人员定义组成对象“标识”的成员并开发适当的相等操作符(通过重载==操作符或Equals方法)。
Saying that two objects are equal if they have the same hash is one way out. However you then have to wonder how the hash is calculated for each instance. Going back to the Person example above, we could use this system if the hash was calculated by looking at the values of the First Name, Last Name, and Social Security Number fields. On top of that, we are then relying on the quality of the hashing method (that's a huge topic on its own, but suffice it to say that not all hashes are created equal, and bad hashing methods can lead to more collisions, which in this case would return false matches).
你是在测试两个对象是否相等吗?即:它们的属性是相等的?
如果是这样的话,你可能会注意到这种情况:
var a = { foo : "bar" };
var b = { foo : "bar" };
alert (a == b ? "Equal" : "Not equal");
// "Not equal"
你可能需要这样做:
function objectEquals(obj1, obj2) {
for (var i in obj1) {
if (obj1.hasOwnProperty(i)) {
if (!obj2.hasOwnProperty(i)) return false;
if (obj1[i] != obj2[i]) return false;
}
}
for (var i in obj2) {
if (obj2.hasOwnProperty(i)) {
if (!obj1.hasOwnProperty(i)) return false;
if (obj1[i] != obj2[i]) return false;
}
}
return true;
}
显然,该函数可以进行相当多的优化,并能够进行深度检查(处理嵌套对象:var a = {foo: {fu: "bar"}}),但您可以理解。
正如FOR所指出的,你可能需要根据自己的目的进行调整,例如:不同的类可能对“equal”有不同的定义。如果您只是处理普通对象,上述方法可能就足够了,否则可以使用自定义MyClass.equals()函数。
我知道这有点老了,但我想添加一个解决方案,我想出了这个问题。 我有一个对象,我想知道它的数据什么时候改变。类似于Object。我所做的是:
function checkObjects(obj,obj2){
var values = [];
var keys = [];
keys = Object.keys(obj);
keys.forEach(function(key){
values.push(key);
});
var values2 = [];
var keys2 = [];
keys2 = Object.keys(obj2);
keys2.forEach(function(key){
values2.push(key);
});
return (values == values2 && keys == keys2)
}
这里可以复制并创建另一组数组来比较值和键。 这很简单,因为它们现在是数组,如果对象大小不同将返回false。
为什么要重新发明轮子?试试Lodash吧。它有许多必须的函数,如isEqual()。
_.isEqual(object, other);
它将使用ECMAScript 5和本地优化(如果它们在浏览器中可用)强力检查每个键值——就像本页上的其他示例一样。
注意:以前这个答案推荐使用Underscore.js,但是lodash在修复bug和一致性解决问题方面做得更好。