严格的相等运算符将告诉您两个对象类型是否相等。但是,有没有办法判断两个对象是否相等,就像 Java 中的哈希码值一样?
堆栈溢出问题JavaScript 中是否存在某种 hashCode 函数?与这个问题相似,但需要更多的学术答案。上面的场景演示了为什么必须要有一个,而我想知道是否有任何等效的解决方案。
为什么要重新发明轮子?试试Lodash。它具有许多必备功能,例如isEqual() 。
_.isEqual(object, other);
就像本页中的其他示例一样,它将使用ECMAScript 5和本机优化(如果浏览器中可用)蛮力检查每个键值。
注:以前这个答案推荐Underscore.js ,但lodash做得越来越修复的错误,并与一致性解决问题的一个更好的工作。
简短的答案
简单的答案是:不,就您的意思而言,没有通用的方法可以确定一个对象与另一个对象相等。例外是,当您严格考虑对象是无类型的时。
长答案
该概念是 Equals 方法的概念,该方法比较对象的两个不同实例以指示它们在值级别上是否相等。但是,由特定类型决定如何Equals
方法。具有原始值的属性的迭代比较可能不够,可能存在一些不被视为对象值一部分的属性。例如,
function MyClass(a, b)
{
var c;
this.getCLazy = function() {
if (c === undefined) c = a * b // imagine * is really expensive
return c;
}
}
在上述情况下, c
对于确定 MyClass 的任何两个实例是否相等a
和b
是重要的。在某些情况下, c
在各个实例之间可能有所不同,但在比较过程中并不重要。
请注意,当成员本身也可能是类型的实例,并且每个成员都必须具有确定相等性的方法时,就会出现此问题。
更为复杂的是,在 JavaScript 中,数据和方法之间的区别变得模糊。
一个对象可以引用一个被称为事件处理程序的方法,而这可能不被认为是其 “值状态” 的一部分。然而,可以很好地为另一个对象分配执行重要计算的功能,从而使该实例与其他实例有所不同,仅仅是因为它引用了一个不同的功能。
如果某个对象的现有原型方法之一被另一个函数覆盖,那该怎么办?还是可以认为它等同于另一个实例,但在其他方面相同吗?对于每种类型,只能在每种特定情况下回答该问题。
如前所述,该异常将是严格无类型的对象。在这种情况下,唯一明智的选择是对每个成员进行迭代和递归比较。即使这样,也必须问一个函数的 “价值” 是什么?
当 JavaScript for Objects 引用内存中的相同位置时,其默认相等运算符将产生 true。
var x = {};
var y = {};
var z = x;
x === y; // => false
x === z; // => true
如果您需要其他相等运算符,则需要在类中添加一个equals(other)
方法或类似的方法,而问题域的具体内容将确定这到底意味着什么。
这是一个纸牌示例:
function Card(rank, suit) {
this.rank = rank;
this.suit = suit;
this.equals = function(other) {
return other.rank == this.rank && other.suit == this.suit;
};
}
var queenOfClubs = new Card(12, "C");
var kingOfSpades = new Card(13, "S");
queenOfClubs.equals(kingOfSpades); // => false
kingOfSpades.equals(new Card(13, "S")); // => true