严格相等运算符将告诉您两个对象类型是否相等。然而,是否有一种方法来判断两个对象是否相等,就像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许可下的开源软件。

其他回答

2022:

我想出了一个非常简单的算法来解决大多数边缘情况。

步骤:

使物体变平 简单地比较两个扁平的物体并寻找差异

如果你保存了平面对象,你可以重复使用它。

let obj1= {var1:'value1', var2:{ var1:'value1', var2:'value2'}};
let obj2 = {var1:'value1', var2:{ var1:'value11',var2:'value2'}} 

let flat1= flattenObject(obj1)
/*
{
 'var1':'value1',
 'var2.var1':'value1',
 'var2.var2':'value2'
}
*/
let flat2= flattenObject(obj2)
/*
{
 'var1':'value1',
 'var2.var1':'value11',
 'var2.var2':'value2'
}
*/
isEqual(flat1, flat2)
/*
 false
*/

当然,您可以为这些步骤提供您的实现。但我的想法是:

实现

function flattenObject(obj) {
 const object = Object.create(null);
 const path = [];
 const isObject = (value) => Object(value) === value;

 function dig(obj) {
  for (let [key, value] of Object.entries(obj)) {
    path.push(key);
    if (isObject(value)) dig(value);
    else object[path.join('.')] = value;
    path.pop();
  }
 }

 dig(obj);
 return object;
}
 function isEqual(flat1, flat2) {
    for (let key in flat2) {
        if (flat1[key] !== flat2[key])
            return false
    }
    // check for missing keys
    for (let key in flat1) {
        if (!(key in flat2))
            return false
    }
    return true
}

你也可以使用这个方法来获取obj1和obj2之间的Diff对象。

看看这个答案的细节:两个对象之间的一般深度差异

ES6:我能做到的最小代码是这样的。它通过对代表对象的所有键值数组进行字符串化来进行递归的深度比较,唯一的限制是没有方法或符号进行比较。

const compareObjects = (a, b) => { let s = (o) => Object.entries(o).sort()。映射(i => { if(i[1]实例对象)i[1] = s(i[1]); 返回我 }) 返回JSON.stringify(s(a)) === JSON.stringify(s(b)) } console.log (compareObjects ({b: 4,答:{b: 1}}, {} {b: 1, b: 4}));

重要提示:这个函数正在执行JSON。stringfy在数组中,并将键排序,而不是在对象本身中:

["a" ["b", 1]] [" b ", 4]

const isEqual = function (var1, var2) {
    if (typeof var1 === 'object' && typeof var2 === 'object') {
        // Checking equality for each of the inner values of the objects
        const keys = [...new Set([...Object.keys(var1),...Object.keys(var2)])];
        return keys.every(key => isEqual(var1[key], var2[key]) && isEqual(var2[key], var1[key]));
    } else { // Primitive types (number, boolean etc..)
        return var1 === var2; // Normal equality
    }
}

我在这里看到了很多很好的答案,但我找不到一个简短的函数,所以我创建了一个。 这将检查两个变量是否相等,无论其类型如何。 希望你看得合适。

简单来说:

const compare = (x, y) => {
  const srt = (obj) => JSON.stringify(obj)?.split('').sort().join('');
  return srt(x) === srt(y);
};

// ----- How to use ---
const a = {'one':1, 'two':2,'three':3};
const b = {'two':2, 'one':1, 'three':3}; //note same values as (const a)
const c = {'one':1, 'two':2,'three':3};
const d = {'one':1, 'two':2,'four':4};

compare(a, b); //true
compare(a, c); //true
compare(a, d); //false

//----- BUT! -----
JSON.stringify(a) === JSON.stringify(b); //false

//----- AND -----
compare({}, {}); //true
compare({}, undefined); //false
compare(undefined, undefined); //true
compare(undefined, ''); //false
compare(undefined, null); //false
compare(null, null); //true
compare('', ''); //true

另外一个选项是使用Ramda库的equals:

const c = {a: 1, b: 2};
const d = {b: 2, a: 1};
R.equals(c, d); //=> true