严格相等运算符将告诉您两个对象类型是否相等。然而,是否有一种方法来判断两个对象是否相等,就像Java中的哈希码值一样?
堆栈溢出问题JavaScript中有hashCode函数吗?类似于这个问题,但需要一个更学术的答案。上面的场景说明了为什么有必要有一个,我想知道是否有等效的解决方案。
严格相等运算符将告诉您两个对象类型是否相等。然而,是否有一种方法来判断两个对象是否相等,就像Java中的哈希码值一样?
堆栈溢出问题JavaScript中有hashCode函数吗?类似于这个问题,但需要一个更学术的答案。上面的场景说明了为什么有必要有一个,我想知道是否有等效的解决方案。
当前回答
我建议不要使用散列或序列化(正如JSON解决方案所建议的那样)。如果需要测试两个对象是否相等,则需要定义相等的含义。这可能是两个对象中的所有数据成员都匹配,也可能是内存位置必须匹配(意味着两个变量在内存中引用同一个对象),或者每个对象中只有一个数据成员必须匹配。
最近我开发了一个对象,它的构造函数在每次创建实例时都会创建一个新的id(从1开始,加1)。该对象有一个isEqual函数,用于将该id值与另一个对象的id值进行比较,如果匹配则返回true。
在这种情况下,我定义“相等”的意思是id值匹配。假设每个实例都有一个唯一的id,这可以用来加强匹配对象也占用相同内存位置的想法。尽管这是不必要的。
其他回答
我已经实现了一个方法,它接受两个json,并使用递归检查它们的键是否具有相同的值。 我用另一个问题来解决这个问题。
const arraysEqual = (a, b) => { if (a === b) return true; if (a === null || b === null) return false; if (a.length !== b.length) return false; // If you don't care about the order of the elements inside // the array, you should sort both arrays here. for (let i = 0; i < a.length; ++i) { if (a[i] !== b[i]) return false; } return true; }; const jsonsEqual = (a, b) => { if(typeof a !== 'object' || typeof b !== 'object') return false; if (Object.keys(a).length === Object.keys(b).length) { // if items have the same size let response = true; for (let key in a) { if (!b[key]) // if not key response = false; if (typeof a[key] !== typeof b[key]) // if typeof doesn't equals response = false; else { if (Array.isArray(a[key])) // if array response = arraysEqual(a[key], b[key]); else if (typeof a[key] === 'object') // if another json response = jsonsEqual(a[key], b[key]); else if (a[key] !== b[key]) // not equals response = false; } if (!response) // return if one item isn't equal return false; } } else return false; return true; }; const json1 = { a: 'a', b: 'asd', c: [ '1', 2, 2.5, '3', { d: 'asd', e: [ 1.6, { f: 'asdasd', g: '123' } ] } ], h: 1, i: 1.2, }; const json2 = { a: 'nops', b: 'asd' }; const json3 = { a: 'h', b: '484', c: [ 3, 4.5, '2ss', { e: [ { f: 'asdasd', g: '123' } ] } ], h: 1, i: 1.2, }; const result = jsonsEqual(json1,json2); //const result = jsonsEqual(json1,json3); //const result = jsonsEqual(json1,json1); if(result) // is equal $('#result').text("Jsons are the same") else $('#result').text("Jsons aren't equals") <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <div id="result"></div>
let user1 = { name: "John", address: { line1: "55 Green Park Road", line2: { a:[1,2,3] } }, email:null } let user2 = { name: "John", address: { line1: "55 Green Park Road", line2: { a:[1,2,3] } }, email:null } // Method 1 function isEqual(a, b) { return JSON.stringify(a) === JSON.stringify(b); } // Method 2 function isEqual(a, b) { // checking type of a And b if(typeof a !== 'object' || typeof b !== 'object') { return false; } // Both are NULL if(!a && !b ) { return true; } else if(!a || !b) { return false; } let keysA = Object.keys(a); let keysB = Object.keys(b); if(keysA.length !== keysB.length) { return false; } for(let key in a) { if(!(key in b)) { return false; } if(typeof a[key] === 'object') { if(!isEqual(a[key], b[key])) { return false; } } else { if(a[key] !== b[key]) { return false; } } } return true; } console.log(isEqual(user1,user2));
我之前添加了一个答案,但它不是完美的,但这个将检查对象的相等性
function equalObjects(myObj1, myObj2){ let firstScore = 0; let secondScore = 0; let index=0; let proprtiesArray = []; let valuesArray = []; let firstLength = 0; let secondLength = 0; for (const key in myObj1) { if (myObj1.hasOwnProperty(key)) { firstLength += 1; proprtiesArray.push(key); valuesArray.push(myObj1[key]); firstScore +=1; } } for (const key in myObj2) { if (myObj2.hasOwnProperty(key)) { secondLength += 1; if (valuesArray[index] === myObj2[key] && proprtiesArray[index] === key) { secondScore +=1; } //console.log(myObj[key]); index += 1; } } if (secondScore == firstScore && firstLength === secondLength) { console.log("true", "equal objects"); return true; } else { console.log("false", "not equal objects"); return false; } } equalObjects({'firstName':'Ada','lastName':'Lovelace'},{'firstName':'Ada','lastName':'Lovelace'}); equalObjects({'firstName':'Ada','lastName':'Lovelace'},{'firstName':'Ada','lastName1':'Lovelace'}); equalObjects({'firstName':'Ada','lastName':'Lovelace'},{'firstName':'Ada','lastName':'Lovelace', 'missing': false});
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]
虽然这个问题已经得到了充分的回答,但我还缺少一种方法: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