我有2个不同的嵌套对象,我需要知道它们是否在其中一个嵌套属性中有不同。
var a = {};
var b = {};
a.prop1 = 2;
a.prop2 = { prop3: 2 };
b.prop1 = 2;
b.prop2 = { prop3: 3 };
对象可以更复杂,有更多嵌套的属性。但这是一个很好的例子。我可以选择使用递归函数或lodash的东西…
我有2个不同的嵌套对象,我需要知道它们是否在其中一个嵌套属性中有不同。
var a = {};
var b = {};
a.prop1 = 2;
a.prop2 = { prop3: 2 };
b.prop1 = 2;
b.prop2 = { prop3: 3 };
对象可以更复杂,有更多嵌套的属性。但这是一个很好的例子。我可以选择使用递归函数或lodash的东西…
当前回答
简单使用_。isEqual方法,它将适用于所有比较…
注意:此方法支持比较数组、数组缓冲区、 布尔值、 *日期对象,错误对象,地图,数字,对象对象,正则表达式, *集合、字符串、符号和类型化数组。对象对象进行比较 *通过自身的,不可继承的,可枚举的属性。函数和DOM *节点不支持。
所以如果你有以下情况:
const firstName = {name: "Alireza"};
const otherName = {name: "Alireza"};
如果是:_。isEqual (firstName, otherName);
它会返回true
如果const fullName = {firstName: "Alireza", familyName: "Dezfoolian"};
如果是:_。isEqual (firstName, fullName);
将返回false
其他回答
简单使用_。isEqual方法,它将适用于所有比较…
注意:此方法支持比较数组、数组缓冲区、 布尔值、 *日期对象,错误对象,地图,数字,对象对象,正则表达式, *集合、字符串、符号和类型化数组。对象对象进行比较 *通过自身的,不可继承的,可枚举的属性。函数和DOM *节点不支持。
所以如果你有以下情况:
const firstName = {name: "Alireza"};
const otherName = {name: "Alireza"};
如果是:_。isEqual (firstName, otherName);
它会返回true
如果const fullName = {firstName: "Alireza", familyName: "Dezfoolian"};
如果是:_。isEqual (firstName, fullName);
将返回false
对于无意中发现这条线索的人,这里有一个更完整的解决方案。它将比较两个对象,并给出所有属性的键,这些属性要么只存在于object1中,要么只存在于object2中,要么同时存在于object1和object2中,但值不同:
/*
* Compare two objects by reducing an array of keys in obj1, having the
* keys in obj2 as the intial value of the result. Key points:
*
* - All keys of obj2 are initially in the result.
*
* - If the loop finds a key (from obj1, remember) not in obj2, it adds
* it to the result.
*
* - If the loop finds a key that are both in obj1 and obj2, it compares
* the value. If it's the same value, the key is removed from the result.
*/
function getObjectDiff(obj1, obj2) {
const diff = Object.keys(obj1).reduce((result, key) => {
if (!obj2.hasOwnProperty(key)) {
result.push(key);
} else if (_.isEqual(obj1[key], obj2[key])) {
const resultKeyIndex = result.indexOf(key);
result.splice(resultKeyIndex, 1);
}
return result;
}, Object.keys(obj2));
return diff;
}
下面是一个输出示例:
// Test
let obj1 = {
a: 1,
b: 2,
c: { foo: 1, bar: 2},
d: { baz: 1, bat: 2 }
}
let obj2 = {
b: 2,
c: { foo: 1, bar: 'monkey'},
d: { baz: 1, bat: 2 }
e: 1
}
getObjectDiff(obj1, obj2)
// ["c", "e", "a"]
如果你不关心嵌套对象并且想要跳过lodash,你可以替换_。isEqual用于正常的值比较,例如obj1[key] === obj2[key]。
我知道这并不能直接回答OP的问题,但我是通过搜索如何删除lodash被引导到这里的。希望这能帮助到和我处境相似的人。
这要归功于@JohanPersson。我在这个答案的基础上实现了对深度嵌套值的比较,并获得对差异的键引用
getObjectDiff = (obj1, obj2) => { const obj1Props = Object.keys(obj1); const obj2Props = Object.keys(obj2); const keysWithDiffValue = obj1Props.reduce((keysWithDiffValueAccumulator, key) => { const propExistsOnObj2 = obj2.hasOwnProperty(key); const hasNestedValue = obj1[key] instanceof Object && obj2[key] instanceof Object; const keyValuePairBetweenBothObjectsIsEqual = obj1[key] === obj2[key]; if (!propExistsOnObj2) { keysWithDiffValueAccumulator.push(key); } else if (hasNestedValue) { const keyIndex = keysWithDiffValueAccumulator.indexOf(key); if (keyIndex >= 0) { keysWithDiffValueAccumulator.splice(keyIndex, 1); } const nestedDiffs = getObjectDiff(obj1[key], obj2[key]); for (let diff of nestedDiffs) { keysWithDiffValueAccumulator.push(`${key}.${diff}`); } } else if (keyValuePairBetweenBothObjectsIsEqual) { const equalValueKeyIndex = keysWithDiffValueAccumulator.indexOf(key); keysWithDiffValueAccumulator.splice(equalValueKeyIndex, 1); } return keysWithDiffValueAccumulator; }, obj2Props); return keysWithDiffValue; } const obj1 = {a0: {a1: {a2: {a3: 'Im here'}}}}; const obj2 = {a0: {a1: {a2: {a3: 'Not here', b3: 'some'}}}}; console.log('final', getObjectDiff(obj1, obj2));
在没有使用lodash/下划线的情况下,我已经编写了这段代码,并且可以很好地对object1和object2进行深入比较
function getObjectDiff(a, b) {
var diffObj = {};
if (Array.isArray(a)) {
a.forEach(function(elem, index) {
if (!Array.isArray(diffObj)) {
diffObj = [];
}
diffObj[index] = getObjectDiff(elem, (b || [])[index]);
});
} else if (a != null && typeof a == 'object') {
Object.keys(a).forEach(function(key) {
if (Array.isArray(a[key])) {
var arr = getObjectDiff(a[key], b[key]);
if (!Array.isArray(arr)) {
arr = [];
}
arr.forEach(function(elem, index) {
if (!Array.isArray(diffObj[key])) {
diffObj[key] = [];
}
diffObj[key][index] = elem;
});
} else if (typeof a[key] == 'object') {
diffObj[key] = getObjectDiff(a[key], b[key]);
} else if (a[key] != (b || {})[key]) {
diffObj[key] = a[key];
} else if (a[key] == (b || {})[key]) {
delete a[key];
}
});
}
Object.keys(diffObj).forEach(function(key) {
if (typeof diffObj[key] == 'object' && JSON.stringify(diffObj[key]) == '{}') {
delete diffObj[key];
}
});
return diffObj;
}
深度比较使用模板的(嵌套)属性进行检查
function objetcsDeepEqualByTemplate(objectA, objectB, comparisonTemplate) {
if (!objectA || !objectB) return false
let areDifferent = false
Object.keys(comparisonTemplate).some((key) => {
if (typeof comparisonTemplate[key] === 'object') {
areDifferent = !objetcsDeepEqualByTemplate(objectA[key], objectB[key], comparisonTemplate[key])
return areDifferent
} else if (comparisonTemplate[key] === true) {
areDifferent = objectA[key] !== objectB[key]
return areDifferent
} else {
return false
}
})
return !areDifferent
}
const objA = {
a: 1,
b: {
a: 21,
b: 22,
},
c: 3,
}
const objB = {
a: 1,
b: {
a: 21,
b: 25,
},
c: true,
}
// template tells which props to compare
const comparisonTemplateA = {
a: true,
b: {
a: true
}
}
objetcsDeepEqualByTemplate(objA, objB, comparisonTemplateA)
// returns true
const comparisonTemplateB = {
a: true,
c: true
}
// returns false
objetcsDeepEqualByTemplate(objA, objB, comparisonTemplateB)
这将在控制台中工作。如果需要,可以添加数组支持