严格相等运算符将告诉您两个对象类型是否相等。然而,是否有一种方法来判断两个对象是否相等,就像Java中的哈希码值一样?

堆栈溢出问题JavaScript中有hashCode函数吗?类似于这个问题,但需要一个更学术的答案。上面的场景说明了为什么有必要有一个,我想知道是否有等效的解决方案。


当前回答

我写了一个运行在Node.js和浏览器上的小库,叫做compare.js。它提供了常见的比较运算符,例如==,!=,>,>=,<,<=和所有JavaScript数据类型的标识符。

例如,你可以用

cmp.eq(obj1, obj2);

这将检查是否相等(使用深度相等的方法)。否则,如果你这样做

cmp.id(obj1, obj2);

它将通过引用进行比较,从而检查标识。 您还可以在对象上使用<和>,它们表示子集和超集。

Compare.js被近700个单元测试覆盖,因此它应该不会有太多的bug;-)。

你可以在https://github.com/goloroden/compare.js上免费找到它,它是MIT许可下的开源软件。

其他回答

这取决于你对平等的定义。因此,作为类的开发人员,要由您来定义它们的相等性。

有时会使用一种情况,如果两个实例指向内存中的相同位置,则认为它们是“相等的”,但这并不总是您想要的。例如,如果我有一个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).

我需要模拟jQuery POST请求,因此对我来说重要的是两个对象具有相同的属性集(任何一个对象中都不缺少属性),并且每个属性值都是“相等的”(根据这个定义)。我不关心对象是否有不匹配的方法。

这是我将使用的,它应该足以满足我的特定要求:

function PostRequest() {
    for (var i = 0; i < arguments.length; i += 2) {
        this[arguments[i]] = arguments[i+1];
    }

    var compare = function(u, v) {
        if (typeof(u) != typeof(v)) {
            return false;
        }

        var allkeys = {};
        for (var i in u) {
            allkeys[i] = 1;
        }
        for (var i in v) {
            allkeys[i] = 1;
        }
        for (var i in allkeys) {
            if (u.hasOwnProperty(i) != v.hasOwnProperty(i)) {
                if ((u.hasOwnProperty(i) && typeof(u[i]) == 'function') ||
                    (v.hasOwnProperty(i) && typeof(v[i]) == 'function')) {
                    continue;
                } else {
                    return false;
                }
            }
            if (typeof(u[i]) != typeof(v[i])) {
                return false;
            }
            if (typeof(u[i]) == 'object') {
                if (!compare(u[i], v[i])) {
                    return false;
                }
            } else {
                if (u[i] !== v[i]) {
                    return false;
                }
            }
        }

        return true;
    };

    this.equals = function(o) {
        return compare(this, o);
    };

    return this;
}

像这样使用:

foo = new PostRequest('text', 'hello', 'html', '<p>hello</p>');
foo.equals({ html: '<p>hello</p>', text: 'hello' });

需要一个比已经发布的更通用的对象比较函数,我炮制了以下。批判赞赏……

Object.prototype.equals = function(iObj) {
  if (this.constructor !== iObj.constructor)
    return false;
  var aMemberCount = 0;
  for (var a in this) {
    if (!this.hasOwnProperty(a))
      continue;
    if (typeof this[a] === 'object' && typeof iObj[a] === 'object' ? !this[a].equals(iObj[a]) : this[a] !== iObj[a])
      return false;
    ++aMemberCount;
  }
  for (var a in iObj)
    if (iObj.hasOwnProperty(a))
      --aMemberCount;
  return aMemberCount ? false : true;
}

对象是否相等检查:JSON.stringify(array1.sort()) === JSON.stringify(array2.sort())

上面的测试还适用于对象数组,在这种情况下使用http://www.w3schools.com/jsref/jsref_sort.asp中记录的排序函数

对于具有平面JSON模式的小型数组可能足够了。

这是一个简单的Javascript函数,用于比较具有简单键值对的两个对象。该函数将返回一个字符串数组,其中每个字符串是到两个对象之间的一个不等式的路径。

function compare(a,b) {
    var paths = [];
    [...new Set(Object.keys(a).concat(Object.keys(b)))].forEach(key=>{
        if(typeof a[key] === 'object' && typeof b[key] === 'object') {
            var results = compare(a[key], b[key]);
            if(JSON.stringify(results)!=='[]') {
                paths.push(...results.map(result=>key.concat("=>"+result)));
            }
        }
        else if (a[key]!==b[key]) {
            paths.push(key);
        }
    })
    return paths;
}

如果你只想比较两个对象,而不知道不等式的路径,你可以这样做:

if(JSON.stringify(compare(object1, object2))==='[]') {
   // the two objects are equal
} else {
   // the two objects are not equal
}