var a = {};
var b = {};
a.prop1 = 2;
a.prop2 = { prop3: 2 };
b.prop1 = 2;
b.prop2 = { prop3: 3 };
该对象可能会变得更加复杂嵌套属性。但这是一个很好的例子。我可以选择使用递归函数或带有lodash的东西...
#1 楼
一个简单而优雅的解决方案是使用_.isEqual
,它可以进行深度比较: var a = {};
var b = {};
a.prop1 = 2;
a.prop2 = { prop3: 2 };
b.prop1 = 2;
b.prop2 = { prop3: 3 };
console.log(_.isEqual(a, b)); // returns false if different
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.min.js"></script>
但是,此解决方案并未显示哪个属性不同。
评论
我知道答案很老,但是我想补充一下,_.isEqual可能非常棘手。如果复制对象并在其中更改一些值,由于引用相同,它仍将显示true。因此,应谨慎使用此功能。
–oruckdeschel
18年9月13日在13:51
@oruckdeschel如果引用相同,则它是同一对象。因此,它是平等的。这是一个棘手的指针。 lodash很棒。
–家伙莫格比
18-09-25在2:09
#2 楼
如果需要知道哪些属性不同,请使用reduce():_.reduce(a, function(result, value, key) {
return _.isEqual(value, b[key]) ?
result : result.concat(key);
}, []);
// → [ "prop2" ]
评论
请注意,这只会输出第一级的不同属性。 (因此,输出不同的属性并不是很深。)
–布洛克
16年5月5日在14:03
同样,这将不会拾取b中不在a中的属性。
– Ed Staub
16年8月23日在23:47
和_.reduce(a,(结果,值,键)=> _.isEqual(value,b [key])?结果:result.concat(key),[])用于单行ES6解决方案
– Dotgreg
17年11月4日,9:36
一个包含键的版本:值let edited = _.reduce(a,function(result,value,key){return _.isEqual(value,b [key])?result:result.concat({[key]:value });},[]);
–Aline Matos
18/09/23在14:31
#3 楼
对于绊倒这个线程的任何人,这是一个更完整的解决方案。它将比较两个对象,并为您提供所有属性的键,这些属性要么仅在object1中,仅在object2中,要么在object1和object2中都具有,但具有不同的值:br />这是一个示例输出: ,例如
_.isEqual
。评论
这个选择的答案对于仅测试相等性是正确的。如果您需要知道有什么区别,没有明显的方法可以列出它们,但是这个答案非常好,只要列出存在差异的顶级属性键即可。 (并且它给出了答案作为一个函数,使它变得可用。)
– Sigfried
16-12-12在13:47
这样做和仅使用_.isEqual(obj1,obj2)有什么区别?为has.OwnProperty添加检查,_。isEqual不做什么?我假设如果obj1具有obj2不具有的属性,则_.isEqual将不会返回true。
– Jaked222
17年8月4日在16:44
@ Jaked222-区别在于isEqual返回一个布尔值,告诉您对象是否相等,而上面的函数告诉您两个对象之间有什么不同(如果它们不同)。如果您只想知道两个对象是否相同,那么isEqual就足够了。但是,在许多情况下,您想知道两个对象之间的区别是什么。例如,如果您想检测某事物前后的变化,然后根据这些变化调度事件。
–约翰·佩尔森(Johan Persson)
17年8月5日在17:28
#4 楼
根据亚当·博杜奇(Adam Boduch)的回答,我编写了此函数,该函数以尽可能深的意义比较两个对象,返回具有不同值的路径以及一个或另一个对象缺少的路径。代码最初不是出于效率考虑而编写的,因此在这方面进行改进是最受欢迎的,但这是基本形式:
var compare = function (a, b) {
var result = {
different: [],
missing_from_first: [],
missing_from_second: []
};
_.reduce(a, function (result, value, key) {
if (b.hasOwnProperty(key)) {
if (_.isEqual(value, b[key])) {
return result;
} else {
if (typeof (a[key]) != typeof ({}) || typeof (b[key]) != typeof ({})) {
//dead end.
result.different.push(key);
return result;
} else {
var deeper = compare(a[key], b[key]);
result.different = result.different.concat(_.map(deeper.different, (sub_path) => {
return key + "." + sub_path;
}));
result.missing_from_second = result.missing_from_second.concat(_.map(deeper.missing_from_second, (sub_path) => {
return key + "." + sub_path;
}));
result.missing_from_first = result.missing_from_first.concat(_.map(deeper.missing_from_first, (sub_path) => {
return key + "." + sub_path;
}));
return result;
}
}
} else {
result.missing_from_second.push(key);
return result;
}
}, result);
_.reduce(b, function (result, value, key) {
if (a.hasOwnProperty(key)) {
return result;
} else {
result.missing_from_first.push(key);
return result;
}
}, result);
return result;
}
您可以使用以下代码段尝试使用代码(建议以全页模式运行):
var compare = function (a, b) {
var result = {
different: [],
missing_from_first: [],
missing_from_second: []
};
_.reduce(a, function (result, value, key) {
if (b.hasOwnProperty(key)) {
if (_.isEqual(value, b[key])) {
return result;
} else {
if (typeof (a[key]) != typeof ({}) || typeof (b[key]) != typeof ({})) {
//dead end.
result.different.push(key);
return result;
} else {
var deeper = compare(a[key], b[key]);
result.different = result.different.concat(_.map(deeper.different, (sub_path) => {
return key + "." + sub_path;
}));
result.missing_from_second = result.missing_from_second.concat(_.map(deeper.missing_from_second, (sub_path) => {
return key + "." + sub_path;
}));
result.missing_from_first = result.missing_from_first.concat(_.map(deeper.missing_from_first, (sub_path) => {
return key + "." + sub_path;
}));
return result;
}
}
} else {
result.missing_from_second.push(key);
return result;
}
}, result);
_.reduce(b, function (result, value, key) {
if (a.hasOwnProperty(key)) {
return result;
} else {
result.missing_from_first.push(key);
return result;
}
}, result);
return result;
}
var a_editor = new JSONEditor($('#a')[0], {
name: 'a',
mode: 'code'
});
var b_editor = new JSONEditor($('#b')[0], {
name: 'b',
mode: 'code'
});
var a = {
same: 1,
different: 2,
missing_from_b: 3,
missing_nested_from_b: {
x: 1,
y: 2
},
nested: {
same: 1,
different: 2,
missing_from_b: 3
}
}
var b = {
same: 1,
different: 99,
missing_from_a: 3,
missing_nested_from_a: {
x: 1,
y: 2
},
nested: {
same: 1,
different: 99,
missing_from_a: 3
}
}
a_editor.set(a);
b_editor.set(b);
var result_editor = new JSONEditor($('#result')[0], {
name: 'result',
mode: 'view'
});
var do_compare = function() {
var a = a_editor.get();
var b = b_editor.get();
result_editor.set(compare(a, b));
}
#objects {} #objects section {
margin-bottom: 10px;
}
#objects section h1 {
background: #444;
color: white;
font-family: monospace;
display: inline-block;
margin: 0;
padding: 5px;
}
.jsoneditor-outer, .ace_editor {
min-height: 230px !important;
}
button:hover {
background: orangered;
}
button {
cursor: pointer;
background: red;
color: white;
text-align: left;
font-weight: bold;
border: 5px solid crimson;
outline: 0;
padding: 10px;
margin: 10px 0px;
}
<link href="https://cdnjs.cloudflare.com/ajax/libs/jsoneditor/5.5.10/jsoneditor.min.css" rel="stylesheet" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/jsoneditor/5.5.10/jsoneditor.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="objects">
<section>
<h1>a (first object)</h1>
<div id="a"></div>
</section>
<section>
<h1>b (second object)</h1>
<div id="b"></div>
</section>
<button onClick="do_compare()">compare</button>
<section>
<h1>result</h1>
<div id="result"></div>
</section>
</div>
评论
我只是修复了该错误,但要让您知道,您应该使用b.hasOwnProperty(key)或b中的键来检查对象b中的键是否存在,而不是使用b [key]!= undefined。对于使用b [key]!= undefined的旧版本,该函数对包含undefined的对象返回了不正确的diff,如compare({disabled:undefined},{disabled:undefined})所示。实际上,旧版本还存在null的问题。您可以通过始终使用===和!==而不是==和!=来避免此类问题。
–罗里·奥凯恩(Rory O'Kane)
17 Mar 23 '17 at 21:28
#5 楼
这是一个简洁的解决方案:_.differenceWith(a, b, _.isEqual);
评论
似乎不适合我使用对象。而是返回一个空数组。
–休假
17年11月22日在11:24
同样用Lodash 4.17.4获取空数组
–aristidesfl
18年1月25日在8:59
@ Z.Khullah如果它以这种方式工作,则不会记录在案。
–布伦登
18年1月29日在17:05
@Brendon,@THughes,@aristidesfl抱歉,我已经混合了一些东西,它可用于对象数组,但不适用于深层对象比较。事实证明,如果两个参数都不是数组,lodash只会返回[]。
– Bernardo Dal Corno
18年1月29日在17:36
看起来它仅适用于数组。但是将对象放入数组中没有问题。 _.differenceWith([object1],[object2],_.isEqual);如果返回的数组为空-这意味着-如果数组不为空则没有区别-有区别
– Shutsman
20/09/14在8:58
#6 楼
要递归显示对象与其他对象的区别,可以将_.reduce与_.isEqual和_.isPlainObject结合使用。在这种情况下,您可以比较a与b的区别或b与a的区别: var a = {prop1: {prop1_1: 'text 1', prop1_2: 'text 2', prop1_3: [1, 2, 3]}, prop2: 2, prop3: 3};
var b = {prop1: {prop1_1: 'text 1', prop1_3: [1, 2]}, prop2: 2, prop3: 4};
var diff = function(obj1, obj2) {
return _.reduce(obj1, function(result, value, key) {
if (_.isPlainObject(value)) {
result[key] = diff(value, obj2[key]);
} else if (!_.isEqual(value, obj2[key])) {
result[key] = value;
}
return result;
}, {});
};
var res1 = diff(a, b);
var res2 = diff(b, a);
console.log(res1);
console.log(res2);
<script src="https://cdn.jsdelivr.net/npm/lodash@4.17.4/lodash.min.js"></script>
#7 楼
此代码返回一个对象,该对象的所有属性具有不同的值,并且两个对象的值也不同。有助于记录差异。var allkeys = _.union(_.keys(obj1), _.keys(obj2));
var difference = _.reduce(allkeys, function (result, key) {
if ( !_.isEqual(obj1[key], obj2[key]) ) {
result[key] = {obj1: obj1[key], obj2: obj2[key]}
}
return result;
}, {});
#8 楼
简单易用的_.isEqual
方法,将适用于所有比较... 注意:此方法支持比较数组,数组缓冲区,
布尔值,
*日期对象,错误对象,映射,数字,
Object
对象,正则表达式,*集,字符串,符号和类型化数组。
Object
对象通过它们自己的而非继承的可枚举属性进行比较。函数和DOM *不支持节点。
因此,如果您具有以下内容:
const firstName = {name: "Alireza"};
const otherName = {name: "Alireza"};
如果执行:
_.isEqual(firstName, otherName);
,它将返回true
如果使用
const fullName = {firstName: "Alireza", familyName: "Dezfoolian"};
如果执行:
_.isEqual(firstName, fullName);
,将返回false
#9 楼
在不使用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;
}
#10 楼
使用(嵌套的)属性模板进行深度比较以检查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)
这将在控制台中工作。如果需要,可以添加阵列支持
#11 楼
我刺了亚当·博杜奇(Adam Boduch)的代码来输出一个深的差异-完全未经测试,但是有片段存在:function diff (obj1, obj2, path) {
obj1 = obj1 || {};
obj2 = obj2 || {};
return _.reduce(obj1, function(result, value, key) {
var p = path ? path + '.' + key : key;
if (_.isObject(value)) {
var d = diff(value, obj2[key], p);
return d.length ? result.concat(d) : result;
}
return _.isEqual(value, obj2[key]) ? result : result.concat(p);
}, []);
}
diff({ foo: 'lol', bar: { baz: true }}, {}) // returns ["foo", "bar.baz"]
评论
就像魅力一样,只是obj1和obj2的顺序很重要。例如:diff({},{foo:'lol',bar:{baz:true}})//返回[]
– amangpt777
17年3月31日在11:04
#12 楼
根据要求,这是一个递归对象比较功能。还有更多。假设此类功能的主要用途是对象检查,我有话要说。当某些差异无关紧要时,完全深入的比较是一个坏主意。例如,TDD断言中的盲目的深度比较使测试变得不必要地脆弱。因此,我想介绍一个更有价值的部分差异。它是对该线程先前贡献的递归模拟。它会忽略在var bdiff = (a, b) =>
_.reduce(a, (res, val, key) =>
res.concat((_.isPlainObject(val) || _.isArray(val)) && b
? bdiff(val, b[key]).map(x => key + '.' + x)
: (!b || val != b[key] ? [key] : [])),
[]);
中不存在的键。BDiff允许在允许其他属性的同时检查期望值,这正是您想要进行自动检查的条件。这允许构建各种高级断言。例如:
var diff = bdiff(expected, actual);
// all expected properties match
console.assert(diff.length == 0, "Objects differ", diff, expected, actual);
// controlled inequality
console.assert(diff.length < 3, "Too many differences", diff, expected, actual);
返回完整的解决方案。使用bdiff构建完整的传统diff很简单:
function diff(a, b) {
var u = bdiff(a, b), v = bdiff(b, a);
return u.filter(x=>!v.includes(x)).map(x=>' < ' + x)
.concat(u.filter(x=>v.includes(x)).map(x=>' | ' + x))
.concat(v.filter(x=>!u.includes(x)).map(x=>' > ' + x));
};
在两个复杂的对象上运行上述函数将输出类似以下内容:
[
" < components.0.components.1.components.1.isNew",
" < components.0.cryptoKey",
" | components.0.components.2.components.2.components.2.FFT.min",
" | components.0.components.2.components.2.components.2.FFT.max",
" > components.0.components.1.components.1.merkleTree",
" > components.0.components.2.components.2.components.2.merkleTree",
" > components.0.components.3.FFTResult"
]
最后,为了一窥值的不同,我们可能希望直接eval()diff输出。为此,我们需要一个较丑陋的bdiff版本,该版本可以输出语法正确的路径:
MIT许可证;)
#13 楼
完善了亚当·博杜奇(Adam Boduch)的答案后,该书考虑了属性的差异const differenceOfKeys = (...objects) =>
_.difference(...objects.map(obj => Object.keys(obj)));
const differenceObj = (a, b) =>
_.reduce(a, (result, value, key) => (
_.isEqual(value, b[key]) ? result : [...result, key]
), differenceOfKeys(b, a));
#14 楼
如果只需要键比较: _.reduce(a, function(result, value, key) {
return b[key] === undefined ? key : []
}, []);
#15 楼
我需要知道它们的嵌套属性之一是否存在差异
其他答案为该问题提供了可能令人满意的解决方案,但是它看起来非常困难且普遍,流行的软件包可以帮助解决此问题,请使用深度软件包。
要使用此软件包,您需要先
npm i deep-object-diff
然后: > 这里有一个更详细的案例,直接从其文档中删除了属性:
const { diff } = require('deep-object-diff');
var a = {};
var b = {};
a.prop1 = 2;
a.prop2 = { prop3: 2 };
b.prop1 = 2;
b.prop2 = { prop3: 3 };
if (!_.isEqual(a, b)) {
const abDiff = diff(a, b);
console.log(abDiff);
/*
{
prop2: {
prop3: 3
}
}
*/
}
// or alternatively
const abDiff = diff(a, b);
if(!_.isEmpty(abDiff)) {
// if a diff exists then they aren't deeply equal
// perform needed actions with diff...
}
有关实现的详细信息和其他用法信息,请参阅该仓库。
评论
不错的库,可用于深差异。
– Vivek Goel
20 Dec 4'在4:57
#16 楼
这是一个带有Lodash深度差异检查器的简单Typescript,它将生成一个新对象,其中包含旧对象和新对象之间的差异。例如,如果我们有:
const oldData = {a: 1, b: 2};
const newData = {a: 1, b: 3};
生成的对象将是:
const result: {b: 3};
它还与多层深层对象兼容,对于数组可能需要一些调整。
import * as _ from "lodash";
export const objectDeepDiff = (data: object | any, oldData: object | any) => {
const record: any = {};
Object.keys(data).forEach((key: string) => {
// Checks that isn't an object and isn't equal
if (!(typeof data[key] === "object" && _.isEqual(data[key], oldData[key]))) {
record[key] = data[key];
}
// If is an object, and the object isn't equal
if ((typeof data[key] === "object" && !_.isEqual(data[key], oldData[key]))) {
record[key] = objectDeepDiff(data[key], oldData[key]);
}
});
return record;
};
#17 楼
我们要求获取两个json更新之间的增量以跟踪数据库更新。也许其他人可以找到帮助。https://gist.github.com/jp6rt/7fcb6907e159d7851c8d59840b669e3d
const {
isObject,
isEqual,
transform,
has,
merge,
} = require('lodash');
const assert = require('assert');
/**
* Perform a symmetric comparison on JSON object.
* @param {*} baseObj - The base object to be used for comparison against the withObj.
* @param {*} withObj - The withObject parameter is used as the comparison on the base object.
* @param {*} invert - Because this is a symmetric comparison. Some values in the with object
* that doesn't exist on the base will be lost in translation.
* You can execute again the function again with the parameters interchanged.
* However you will lose the reference if the value is from the base or with
* object if you intended to do an assymetric comparison.
* Setting this to true will do make sure the reference is not lost.
* @returns - The returned object will label the result of the comparison with the
* value from base and with object.
*/
const diffSym = (baseObj, withObj, invert = false) => transform(baseObj, (result, value, key) => {
if (isEqual(value, withObj[key])
&& has(withObj, key)) {
return;
}
if (isObject(value)
&& isObject(withObj[key])
&& !Array.isArray(value)) {
result[key] = diffSym(value, withObj[key], invert);
return;
}
if (!invert) {
result[key] = {
base: value,
with: withObj[key],
};
return;
}
if (invert) {
result[key] = {
base: withObj[key],
with: value,
};
}
});
/**
* Perform a assymmetric comparison on JSON object.
* @param {*} baseObj - The base object to be used for comparison against the withObj.
* @param {*} withObj - The withObject parameter is used as the comparison on the base object.
* @returns - The returned object will label the values with
* reference to the base and with object.
*/
const diffJSON = (baseObj, withObj) => {
// Deep clone the objects so we don't update the reference objects.
const baseObjClone = JSON.parse(JSON.stringify(baseObj));
const withObjClone = JSON.parse(JSON.stringify(withObj));
const beforeDelta = diffSym(baseObjClone, withObjClone);
const afterDelta = diffSym(withObjClone, baseObjClone, true);
return merge(afterDelta, beforeDelta);
};
// By Example:
const beforeDataObj = {
a: 1,
c: { d: 2, f: 3 },
g: 4,
h: 5,
};
const afterDataObj = {
a: 2,
b: 3,
c: { d: 1, e: 1 },
h: 5,
};
const delta = diffJSON(beforeDataObj, afterDataObj);
// Assert expected result.
assert(isEqual(delta, {
a: { base: 1, with: 2 },
b: { base: undefined, with: 3 },
c: {
d: { base: 2, with: 1 },
e: { base: undefined, with: 1 },
f: { base: 3, with: undefined },
},
g: { base: 4, with: undefined },
}));
#18 楼
var isEqual = function(f,s) {
if (f === s) return true;
if (Array.isArray(f)&&Array.isArray(s)) {
return isEqual(f.sort(), s.sort());
}
if (_.isObject(f)) {
return isEqual(f, s);
}
return _.isEqual(f, s);
};
评论
这是无效的。您不能直接用===比较对象,{a:20} === {a:20}将返回false,因为它比较原型。主要比较对象的更正确方法是将它们包装到JSON.stringify()中
– Herrgott
17年8月13日在6:06
如果(f === s)返回true; -仅用于递归。是a:20} === {a:20}将返回false并转到下一个条件
–十字军
17年8月30日在7:32
为什么不仅是_.isEqual(f,s)? :)
– Herrgott
17年8月30日在8:46
这将导致无限递归循环,因为如果f是一个对象并且您到达if(_.isObject(f)),则只需返回该函数并再次达到该点。 f(Array.isArray(f)&& Array.isArray(s))也是如此
–rady
17年11月28日在20:09
#19 楼
这是我对问题的解决方法const _ = require('lodash');
var objects = [{ 'x': 1, 'y': 2, 'z':3, a:{b:1, c:2, d:{n:0}}, p:[1, 2, 3] }, { 'x': 2, 'y': 1, z:3, a:{b:2, c:2,d:{n:1}}, p:[1,3], m:3 }];
const diffFn=(a,b, path='')=>_.reduce(a, function(result, value, key) {
if(_.isObjectLike(value)){
if(_.isEqual(value, b[key])){
return result;
}else{
return result.concat(diffFn(value, b[key], path?(`${path}.${key}`):key))
}
}else{
return _.isEqual(value, b[key]) ?
result : result.concat(path?(`${path}.${key}`):key);
}
}, []);
const diffKeys1=diffFn(objects[0], objects[1])
const diffKeys2=diffFn(objects[1], objects[0])
const diffKeys=_.union(diffKeys1, diffKeys2)
const res={};
_.forEach(diffKeys, (key)=>_.assign(res, {[key]:{ old: _.get(objects[0], key), new:_.get(objects[1], key)} }))
res
/*
Returns
{
x: { old: 1, new: 2 },
y: { old: 2, new: 1 },
'a.b': { old: 1, new: 2 },
'a.d.n': { old: 0, new: 1 },
'p.1': { old: 2, new: 3 },
'p.2': { old: 3, new: undefined },
m: { old: undefined, new: 3 }
}
*/
#20 楼
这是基于@JLavoie的,使用lodashlet differences = function (newObj, oldObj) {
return _.reduce(newObj, function (result, value, key) {
if (!_.isEqual(value, oldObj[key])) {
if (_.isArray(value)) {
result[key] = []
_.forEach(value, function (innerObjFrom1, index) {
if (_.isNil(oldObj[key][index])) {
result[key].push(innerObjFrom1)
} else {
let changes = differences(innerObjFrom1, oldObj[key][index])
if (!_.isEmpty(changes)) {
result[key].push(changes)
}
}
})
} else if (_.isObject(value)) {
result[key] = differences(value, oldObj[key])
} else {
result[key] = value
}
}
return result
}, {})
}
https://jsfiddle.net/EmilianoBarboza/0g0sn3b9/8/
#21 楼
为了建立Sridhar Gudimela的答案,这里使用TypeScript对其进行更新:流,因此不赞成投票(我想,或者也许是因为我的答案未使用Lodash ...但是,对类似问题的答案也不会受到伤害)。#22 楼
只是使用香草js let a = {};
let b = {};
a.prop1 = 2;
a.prop2 = { prop3: 2 };
b.prop1 = 2;
b.prop2 = { prop3: 3 };
JSON.stringify(a) === JSON.stringify(b);
// false
b.prop2 = { prop3: 2};
JSON.stringify(a) === JSON.stringify(b);
// true
评论
此方法不会告诉您哪些属性不同。
– JLavoie
19-10-10在3:09
在这种情况下,属性顺序会影响结果。
–维克多·奥利维拉(Victor Oliveira)
19年11月21日在13:44
评论
进行深层比较stackoverflow.com/a/46003894/696535_.isEqual(value,other)在两个值之间进行深度比较以确定它们是否等效。 lodash.com/docs#isEqual
JSON.stringify()
JSON.stringify()错误:JSON.stringify({a:1,b:2})!== JSON.stringify({b:2,a:1})