严格相等运算符将告诉您两个对象类型是否相等。然而,是否有一种方法来判断两个对象是否相等,就像Java中的哈希码值一样?
堆栈溢出问题JavaScript中有hashCode函数吗?类似于这个问题,但需要一个更学术的答案。上面的场景说明了为什么有必要有一个,我想知道是否有等效的解决方案。
严格相等运算符将告诉您两个对象类型是否相等。然而,是否有一种方法来判断两个对象是否相等,就像Java中的哈希码值一样?
堆栈溢出问题JavaScript中有hashCode函数吗?类似于这个问题,但需要一个更学术的答案。上面的场景说明了为什么有必要有一个,我想知道是否有等效的解决方案。
当前回答
let std1 = {
name: "Abhijeet",
roll: 1
}
let std2 = {
name: "Siddharth",
roll: 2
}
console.log(JSON.stringify(std1) === JSON.stringify(std2))
其他回答
在对象中(没有方法),我们需要检查嵌套的对象,数组和基本类型。对象可以有其他对象和数组(数组也可以包括其他对象和数组),所以我们可以使用如下所示的递归函数:arrayEquals检查数组是否相等,equals检查对象是否相等:
function arrayEquals(a, b) {
if (a.length != b.length) {
return false;
}
for (let i = 0; i < a.length; i++) {
if (a[i].constructor !== b[i].constructor) {
return false;
}
if (a[i] instanceof Array && b[i] instanceof Array) {
if (!arrayEquals(a, b)) {
return false;
}
} else if (a[i] instanceof Object && b[i] instanceof Object) {
if (!equals(a[i], b[i])) {
return false;
}
} else if (a[i] !== b[i]) {
return false;
}
}
return true;
}
function equals(a, b) {
for (let el in a) {
if (b.hasOwnProperty(el)) {
if (a[el].constructor !== b[el].constructor) {
return false;
}
if (a[el] instanceof Array && b[el] instanceof Array) {
if (!arrayEquals(a[el], b[el])) {
return false;
}
} else if (a[el] instanceof Object && b[el] instanceof Object) {
if (!equals(a[el], b[el])) {
return false;
}
} else if (a[el] !== b[el]) {
return false;
}
} else {
return false;
}
}
return true;
}
假设你有两个对象:
let a = {
a: 1,
b: { c: 1, d: "test" },
c: 3,
d: [{ a: [1, 2], e: 2 }, "test", { c: 3, q: 5 }],
};
let b = {
a: 1,
b: { c: 1, d: "test" },
c: 3,
d: [{ a: [1, 2], e: 2 }, "test", { c: 3, q: 5 }],
};
在这里使用上面的equals函数,你可以很容易地比较这两个对象,像这样:
if(equals(a, b)) {
// do whatever you want
}
我看到了意大利式的代码答案。 不使用任何第三方的lib,这是非常容易的。
首先,按键对两个对象进行排序。
let objectOne = { hey, you }
let objectTwo = { you, hey }
// If you really wanted you could make this recursive for deep sort.
const sortObjectByKeyname = (objectToSort) => {
return Object.keys(objectToSort).sort().reduce((r, k) => (r[k] = objectToSort[k], r), {});
}
let objectOne = sortObjectByKeyname(objectOne)
let objectTwo = sortObjectByKeyname(objectTwo)
然后简单地使用字符串来比较它们。
JSON.stringify(objectOne) === JSON.stringify(objectTwo)
这是一个简单的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
}
虽然这个问题已经得到了充分的回答,但我还缺少一种方法:toJSON接口。
通常你想通过字符串化来比较object,因为这是最快的方法。但往往比较被认为是假的,因为性质的顺序。
const obj1 = {
a: 1,
b: 2,
c: {
ca: 1,
cb: 2
}
}
const obj2 = {
b: 2, // changed order with a
a: 1,
c: {
ca: 1,
cb: 2
}
}
JSON.stringify(obj1) === JSON.stringify(obj2) // false
显然,对象被认为是不同的,因为属性a和b的顺序不同。
要解决这个问题,可以实现toJSON接口,并定义一个确定性输出。
const obj1 = {
a: 1,
b: 2,
c: {
ca: 1,
cb: 2
},
toJSON() {
return {
a: this.a,
b: this.b,
c: {
ca: this.c.ca,
cb: this.c.ca
}
}
}
}
const obj2 = {
b: 2,
a: 1,
c: {
ca: 1,
cb: 2
},
toJSON() {
return {
a: this.a,
b: this.b,
c: {
ca: this.c.ca,
cb: this.c.ca
}
}
}
}
JSON.stringify(obj1) === JSON.stringify(obj2) // true
瞧:obj1和obj2的字符串表示被认为是相同的。
TIP
如果你没有直接生成对象的权限,你可以简单地附加toJSON函数:
obj1.toJSON = function() {
return {
a: this.a,
b: this.b,
c: {
ca: this.c.ca,
cb: this.c.ca
}
}
}
obj2.toJSON = function() {
return {
a: this.a,
b: this.b,
c: {
ca: this.c.ca,
cb: this.c.ca
}
}
}
JSON.stringify(obj1) === JSON.stringify(obj2) // true
如何确定部分对象(partial <T>)等于typescript中的原始对象(T)。
function compareTwoObjects<T>(original: T, partial: Partial<T>): boolean {
return !Object.keys(partial).some((key) => partial[key] !== original[key]);
}
附注:最初我打算提出一个有答案的新问题。但这样的问题已经存在,并被标记为重复题。