比较JavaScript中的嵌套对象和返回键

比较JavaScript中的嵌套对象和返回键,javascript,Javascript,我有两个嵌套对象obj1和obj2,我想对它们进行比较,然后递归返回一个对象,该对象对于每个嵌套键都有一个类似相等的布尔标志 因此对于给定的obj1类 obj1 = { prop1: 1, prop2: "foo", prop3: { prop4: 2, prop5: "bar" } } obj2 = { prop1: 3, prop2: "foo", prop3: { prop4: 2, p

我有两个嵌套对象
obj1
obj2
,我想对它们进行比较,然后递归返回一个对象,该对象对于每个嵌套键都有一个类似相等的布尔标志

因此对于给定的
obj1

obj1 = {
  prop1: 1,
  prop2: "foo",
  prop3: {
    prop4: 2,
    prop5: "bar" 
  }
}
obj2 = {
      prop1: 3,
      prop2: "foo",
      prop3: {
        prop4: 2,
        prop5: "foobar" 
      },
      prop6: "new"
    }
obj2
类似

obj1 = {
  prop1: 1,
  prop2: "foo",
  prop3: {
    prop4: 2,
    prop5: "bar" 
  }
}
obj2 = {
      prop1: 3,
      prop2: "foo",
      prop3: {
        prop4: 2,
        prop5: "foobar" 
      },
      prop6: "new"
    }
它应该会回来

equality = {
     prop1: false,
     prop2: true,
     prop3 : {
       prop4: true,
       prop5: false
     },
     prop6: false
   }
如果对象有一个新属性,如
obj2.prop6
,则相等值将为
equality.prop6=false

对于非嵌套对象,这里有一个简单的键比较解决方案
要递归比较嵌套对象,此处显示了

,您可以迭代所有键并检查嵌套对象(如果两个值都是对象)

const isObject=v=>v&&typeof v=='object';
函数getDifference(a,b){
返回Object.assign(…Array.from)(
新集合([…对象.键(a),…对象.键(b)],
k=>({[k]:isObject(a[k])&isObject(b[k])
?getDifference(a[k],b[k])
:a[k]==b[k]
})
));
}
var obj1={prop1:1,prop2:“foo”,prop3:{prop4:2,prop5:“bar”},
obj2={prop1:3,prop2:“foo”,prop3:{prop4:2,prop5:“foobar”},prop6:“new”};

console.log(getDifference(obj1,obj2))
您可以创建一个
合并的
对象,该对象将具有两个对象的键。循环此对象,并比较每个键的
obj1
obj2
值。如果属性是对象,则递归比较属性。这将适用于任何级别的嵌套。由于任何一个对象都可能缺少属性,因此添加了
={}

const obj1={prop1:1,prop2:“foo”,prop3:{prop4:2,prop5:“bar”},prop7:{pro8:“仅在1”},
obj2={prop1:3,prop2:“foo”,prop3:{prop4:2,prop5:“foobar”},prop6:“仅在2”};
const isObject=val=>typeof val==='object'&&val//需要进行“null”比较
函数比较(obj1={},obj2={}){
常量输出={},
merged={…obj1,…obj2};//具有这两个属性
for(合并中的常量键){
常数值1=obj1[键],
value2=obj2[键];
if(等分对象(值1)| |等分对象(值2))
output[key]=compare(value1,value2)//递归调用
其他的
输出[键]=值1==值2
}
返回输出;
}

console.log(compare(obj1,obj2))
您可以使用
reduce
构建新对象,使用另一个
get
方法通过
string
从其他对象获取嵌套的道具,并将其与第一个对象中的当前道具值进行比较

const obj1={prop1:1,prop2:“foo”,prop3:{prop4:2,prop5:“bar”}
const obj2={prop1:3,prop2:“foo”,prop3:{prop4:2,prop5:“foobar”}
函数get(对象,路径){
返回路径.拆分('.').reduce((r,e)=>{
如果(!r)返回r
else返回r[e]| |未定义
},obj)
}
函数比较(a、b、prev=“”){
返回Object.keys(a).reduce((r,e)=>{
常量路径=上一个+(上一个?'.+e:e);
常量值=a[e]==get(b,路径);
r[e]=a[e]=“对象”的类型?比较(a[e],b,路径):值
返回r;
}, {})
}
常数结果=比较(obj1、obj2);
console.log(result)
一个递归示例

var obj1={
prop1:1,
prop2:“foo”,
提案3:{
prop4:2,
建议5:“酒吧”
},
prop7:{},
}
变量obj2={
prop1:3,
prop2:“foo”,
提案3:{
prop4:2,
prop5:“foobar”
},
prop6:“新”,
prop7:{},
prop8:{},
}
var result={};
功能比较(obj1、obj2、obj){
用于(让k进入obj1){
var类型=obj1的类型[k];
如果(类型==‘对象’){
obj_k]={};
如果(!obj2[k]){
obj_k]=假;
}else if((Object.entries(obj1[k]).length==0&&obj1[k]。构造函数===Object)&&(Object.entries(obj2[k]).length==0&&obj2[k]。构造函数===Object)){
obj_k]=真;
}否则{
比较(obj1[k]、obj2[k]、obj_k]);
}
}否则{
obj_k]=(obj1[k]==obj2[k]);
}
}
}
if(Object.keys(obj1).length控制台日志(结果)这是我最近提出的一个解决方案,可以处理相同的问题,它需要一个可选键来设置比较严格性。当后端以数字形式发送值,但希望该值以字符串形式返回时,此选项非常有用。我们一直在使用JSON.stringify比较,但它有点粗糙,无法解释对象相同但键顺序不同的情况

public objectsAreTheSame(objA: {[key: string]: any}, objB: {[key: string]: any}, isStrict = false): boolean {
        let areTheSame = true;

        const strictLevel = isStrict ? 'isStrict' : 'isNotStrict';

        const valuesDoNotMatch = {
            'isStrict': (a, b) => a !== b,
            'isNotStrict': (a, b) => a != b
        };

        const isObject = (a, b) => typeof a === 'object' && !Array.isArray(a) && (!!a && !!b);

        const compareArrays = (a, b) => {
            if (a.length === b.length) {
                a.sort();
                b.sort();

                a.forEach((ele, idx) => compareValues(ele, b[idx]));
            } else {
                areTheSame = false;
            }
        };

        const compareValues = (a, b) => {
            if (Array.isArray(a)) {
                compareArrays(a, b);
            } else if (!isObject(a, b) && valuesDoNotMatch[strictLevel](a, b)) {
                areTheSame = false;
            } else if (isObject(a, b) && !this.objectsAreTheSame(a, b, isStrict)) {
                areTheSame = false;
            }
        };

        const keysA = Object.keys(objA);
        const keysB = Object.keys(objB);

        if (keysA.length !== keysB.length) return false;

        for (let key of keysA) compareValues(objA[key], objB[key]);

        return areTheSame;
    }

两个对象是否总是具有精确的匹配属性?很好。否,因此等式可以将新键设置为
false
。用这一点更新。谢谢。一位投稿人在他的问题中提到了这个链接,他有一个深嵌套对象数组作为输入,所以我想,我应该参考我的感谢,刚刚更新了代码,假设你也可以有新属性。如果obj1有一些键,子obj作为它的值,而obj2没有相同的键怎么办,然后将使用compare(obj1,未定义)调用该方法,这将在obj2[key]@adiga处抛出一个错误。不确定,但问题中的注释确实提到了这一点,并且更新的问题也提到了这一点。不能假设额外的ket始终有一个字符串值。@AZ_u更新。不确定它是否会在任何场景下失败,我认为这是最好的解决方案,因为它支持所有最新版本的ECMAScript。不过,假设该属性是像
{}
这样的空对象,它不会进行比较。好的,现在它处理嵌套的
prop11={}
对象,但是如果