严格相等运算符将告诉您两个对象类型是否相等。然而,是否有一种方法来判断两个对象是否相等,就像Java中的哈希码值一样?
堆栈溢出问题JavaScript中有hashCode函数吗?类似于这个问题,但需要一个更学术的答案。上面的场景说明了为什么有必要有一个,我想知道是否有等效的解决方案。
严格相等运算符将告诉您两个对象类型是否相等。然而,是否有一种方法来判断两个对象是否相等,就像Java中的哈希码值一样?
堆栈溢出问题JavaScript中有hashCode函数吗?类似于这个问题,但需要一个更学术的答案。上面的场景说明了为什么有必要有一个,我想知道是否有等效的解决方案。
当前回答
我发现比较两个javascript对象的值而忽略属性顺序的一个简单方法是使用JSON stringify replacer函数:
const compareReplacer = (key, value) => {
if(typeof value === 'object' && !(value instanceof Array))
return Object.entries(value).sort();
return value;
}
export const compareObjects = (a, b) => JSON.stringify(a, compareReplacer) === JSON.stringify(b, compareReplacer);
这将在每一步对属性进行排序,以便字符串结果对属性顺序不变。以前可能有人这样做过,但我只是想分享一下,以防万一:)。
其他回答
排序对象(字典) 比较JSON字符串 函数areTwoDictsEqual(dictA, dictB) { 函数sortDict(dict) { var keys = Object.keys(dict); keys.sort (); var newDict = {}; For (var i=0;我< keys.length;我+ +){ Var key = keys[i]; Var值= dict[key]; newDict[key] = value; } 返回newDict; } 返回JSON.stringify(sortDict(dictA)) == JSON.stringify(sortDict(dictB)); }
你是在测试两个对象是否相等吗?即:它们的属性是相等的?
如果是这样的话,你可能会注意到这种情况:
var a = { foo : "bar" };
var b = { foo : "bar" };
alert (a == b ? "Equal" : "Not equal");
// "Not equal"
你可能需要这样做:
function objectEquals(obj1, obj2) {
for (var i in obj1) {
if (obj1.hasOwnProperty(i)) {
if (!obj2.hasOwnProperty(i)) return false;
if (obj1[i] != obj2[i]) return false;
}
}
for (var i in obj2) {
if (obj2.hasOwnProperty(i)) {
if (!obj1.hasOwnProperty(i)) return false;
if (obj1[i] != obj2[i]) return false;
}
}
return true;
}
显然,该函数可以进行相当多的优化,并能够进行深度检查(处理嵌套对象:var a = {foo: {fu: "bar"}}),但您可以理解。
正如FOR所指出的,你可能需要根据自己的目的进行调整,例如:不同的类可能对“equal”有不同的定义。如果您只是处理普通对象,上述方法可能就足够了,否则可以使用自定义MyClass.equals()函数。
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
}
}
我在这里看到了很多很好的答案,但我找不到一个简短的函数,所以我创建了一个。 这将检查两个变量是否相等,无论其类型如何。 希望你看得合适。
我需要模拟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' });
下面是一个使用ES6+的解决方案
// this comparison would not work for function and symbol comparisons
// this would only work best for compared objects that do not belong to same address in memory
// Returns true if there is no difference, and false otherwise
export const isObjSame = (obj1, obj2) => {
if (typeof obj1 !== "object" && obj1 !== obj2) {
return false;
}
if (typeof obj1 !== "object" && typeof obj2 !== "object" && obj1 === obj2) {
return true;
}
if (typeof obj1 === "object" && typeof obj2 === "object") {
if (Array.isArray(obj1) && Array.isArray(obj2)) {
if (obj1.length === obj2.length) {
if (obj1.length === 0) {
return true;
}
const firstElemType = typeof obj1[0];
if (typeof firstElemType !== "object") {
const confirmSameType = currentType =>
typeof currentType === firstElemType;
const checkObjOne = obj1.every(confirmSameType);
const checkObjTwo = obj2.every(confirmSameType);
if (checkObjOne && checkObjTwo) {
// they are primitves, we can therefore sort before and compare by index
// use number sort
// use alphabet sort
// use regular sort
if (firstElemType === "string") {
obj1.sort((a, b) => a.localeCompare(b));
obj2.sort((a, b) => a.localeCompare(b));
}
obj1.sort((a, b) => a - b);
obj2.sort((a, b) => a - b);
let equal = true;
obj1.map((element, index) => {
if (!isObjSame(element, obj2[index])) {
equal = false;
}
});
return equal;
}
if (
(checkObjOne && !checkObjTwo) ||
(!checkObjOne && checkObjTwo)
) {
return false;
}
if (!checkObjOne && !checkObjTwo) {
for (let i = 0; i <= obj1.length; i++) {
const compareIt = isObjSame(obj1[i], obj2[i]);
if (!compareIt) {
return false;
}
}
return true;
}
// if()
}
const newValue = isObjSame(obj1, obj2);
return newValue;
} else {
return false;
}
}
if (!Array.isArray(obj1) && !Array.isArray(obj2)) {
let equal = true;
if (obj1 && obj2) {
const allKeys1 = Array.from(Object.keys(obj1));
const allKeys2 = Array.from(Object.keys(obj2));
if (allKeys1.length === allKeys2.length) {
allKeys1.sort((a, b) => a - b);
allKeys2.sort((a, b) => a - b);
allKeys1.map((key, index) => {
if (
key.toLowerCase() !== allKeys2[index].toLowerCase()
) {
equal = false;
return;
}
const confirmEquality = isObjSame(obj1[key], obj2[key]);
if (!confirmEquality) {
equal = confirmEquality;
return;
}
});
}
}
return equal;
// return false;
}
}
};