比较对象并删除相等的值

问题描述

我希望能够比较两个对象并删除未更改值的属性

prevObject = {
  isActive: true,userName: 'Patric',settings: {
    isUser: true
  }
}


nextObject = {
  isActive: true,userName: 'Patric Surname',settings: {
    isUser: false
  }
}

以上比较的结果应为:

{
  userName: 'Patric Surname',settings: {
    isUser: false
  }
}

我已经尝试了一些for循环等,但是我没有让它递归地工作。抱歉,我没有任何代码可以证明我已经尝试过了。我有点沮丧,所以把它丢了。我还坚持使用纯ES5。所以没有破折号或下划线:)

真的很高兴获得帮助!

解决方法

您将需要一种递归方法:

使用ECMAScript-5语法:

function isObject(a) {
    return typeof a === "object" && a;
}

function diff(a,b) {
    var res = b instanceof Array ? [] : {};
    for (var prop in b) {
        if (!(prop in a) || (!isObject(a[prop]) || !isObject(b[prop])) && a[prop] !== b[prop]) {
            res[prop] = b[prop];
        } else {
            var obj = diff(a[prop],b[prop]);
            // If the recursive result is not an empty object,then use it
            for (var _ in obj) {
                res[prop] = obj;
                break; // We only need 1 iteration
            }
        }
    }
    return res; 
}

var prevObject = {isActive: true,userName: 'Patric',settings: {isUser: true }};
var nextObject = { isActive: true,userName: 'Patric Surname',settings: {isUser: false}};

console.log(diff(prevObject,nextObject));

此函数对数组的支持有限。仅当数组元素的内容相同并且在数组中出现的位置的索引相同时,才认为它们相同。这意味着结果数组可能有间隙(“稀疏”)。

,

var prevObject = {
  isActive: true,settings: {
    isUser: true
  }
};

var nextObject = {
  isActive: true,settings: {
    isUser: false
  }
};

var changes = Object.entries(nextObject).reduce((acc,cv)=>{
  if(JSON.stringify(nextObject[cv[0]]) != JSON.stringify(prevObject[cv[0]]))
    acc.push(cv);
  return acc;
},[]).reduce((acc,cv)=>{
  acc[cv[0]]=cv[1];
  return acc;
},{});

console.log(changes);

假设prevObjectnextObject具有相同的属性。
Object.entries中的nextObject返回Array s中的[key,value]
将该reduce上的Array的返回值初始化为空的Array-[]
如果属性JSON.stringify不同,则用属性填充。
JSON.stringify比较使我们免于检查类型等。例如:[1,2,3]不等于[1,3],但是JSON.stringify([1,3])==JSON.stringify([1,3])是。对象等也一样
我们在最后创建的reduce上使用Array,并以{}作为初始值,将属性(cv[0])及其值(cv[1])填充回{ {1}}。