两个对象之间的一般深度差异

我有两个对象:oldObjnewObj

输入的数据oldObj用于填充表单,newObj是用户更改此表单中的数据并提交后的结果。

两个物体都很深,即。它们具有对象或对象数组等属性-它们的深度可以为n级,因此diff算法需要递归。

现在我需要不只是从弄清楚什么改变(如添加/更新/删除)oldObjnewObj,却怎么也最能代表它。

到目前为止,我的想法只是建立一个genericDeepDiffBetweenObjects将在表单上返回对象的方法,{add:{...},upd:{...},del:{...}}但随后我想到:之前一定有人需要此方法。

那么…是否有人知道可以做到这一点的库或一段代码,也许有一种更好的方式来表示差异(以仍可序列化JSON的方式)?

更新:

我想过一种更好的方式来表示更新的数据,方法是使用与相同的对象结构newObj,但将所有属性值都转换为表单上的对象:

{type: '<update|create|delete>', data: <propertyValue>}

所以如果newObj.prop1 = 'new value'oldObj.prop1 = 'old

value'它将设置returnObj.prop1 = {type: 'update', data: 'new value'}

更新2:

当我们进入数组的属性时,它确实变得毛茸茸,因为该数组[1,2,3]应被视为等于[2,3,1],对于基于值的类型(如string,int和bool)的数组而言,这足够简单,但是当涉及到引用类型的数组,例如对象和数组。

应该找到相等的示例数组:

[1,[{c: 1},2,3],{a:'hey'}] and [{a:'hey'},1,[3,{c: 1},2]]

检查这种类型的深价值平等不仅很复杂,而且要找到一种表示可能发生的变化的好方法。

回答:

我写了一个小班,可以做您想做的事,您可以在这里进行测试。

与您的建议唯一不同的是,我认为不[1,[{c: 1},2,3],{a:'hey'}] and [{a:'hey'},1,[3,{c:

1},2]]一样,因为我认为如果数组的元素顺序不相同,数组就不相等。当然,如果需要,可以更改。同样,可以进一步增强此代码以将函数用作参数,该参数将用于基于传递的原始值以任意方式格式化diff对象(现在,此工作由“

compareValues”方法完成)。

var deepDiffMapper = function () {

return {

VALUE_CREATED: 'created',

VALUE_UPDATED: 'updated',

VALUE_DELETED: 'deleted',

VALUE_UNCHANGED: 'unchanged',

map: function(obj1, obj2) {

if (this.isFunction(obj1) || this.isFunction(obj2)) {

throw 'Invalid argument. Function given, object expected.';

}

if (this.isValue(obj1) || this.isValue(obj2)) {

return {

type: this.compareValues(obj1, obj2),

data: obj1 === undefined ? obj2 : obj1

};

}

var diff = {};

for (var key in obj1) {

if (this.isFunction(obj1[key])) {

continue;

}

var value2 = undefined;

if (obj2[key] !== undefined) {

value2 = obj2[key];

}

diff[key] = this.map(obj1[key], value2);

}

for (var key in obj2) {

if (this.isFunction(obj2[key]) || diff[key] !== undefined) {

continue;

}

diff[key] = this.map(undefined, obj2[key]);

}

return diff;

},

compareValues: function (value1, value2) {

if (value1 === value2) {

return this.VALUE_UNCHANGED;

}

if (this.isDate(value1) && this.isDate(value2) && value1.getTime() === value2.getTime()) {

return this.VALUE_UNCHANGED;

}

if (value1 === undefined) {

return this.VALUE_CREATED;

}

if (value2 === undefined) {

return this.VALUE_DELETED;

}

return this.VALUE_UPDATED;

},

isFunction: function (x) {

return Object.prototype.toString.call(x) === '[object Function]';

},

isArray: function (x) {

return Object.prototype.toString.call(x) === '[object Array]';

},

isDate: function (x) {

return Object.prototype.toString.call(x) === '[object Date]';

},

isObject: function (x) {

return Object.prototype.toString.call(x) === '[object Object]';

},

isValue: function (x) {

return !this.isObject(x) && !this.isArray(x);

}

}

}();

var result = deepDiffMapper.map({

a: 'i am unchanged',

b: 'i am deleted',

e: {

a: 1,

b: false,

c: null

},

f: [1, {

a: 'same',

b: [{

a: 'same'

}, {

d: 'delete'

}]

}],

g: new Date('2017.11.25')

}, {

a: 'i am unchanged',

c: 'i am created',

e: {

a: '1',

b: '',

d: 'created'

},

f: [{

a: 'same',

b: [{

a: 'same'

}, {

c: 'create'

}]

}, 1],

g: new Date('2017.11.25')

});

console.log(result);

以上是 两个对象之间的一般深度差异 的全部内容, 来源链接: utcz.com/qa/403864.html

回到顶部