合并两个对象而不删除原始属性

时间:2019-03-08 16:21:16

标签: javascript

我有两个对象,分别是Object1Object2

var Object1 = {    
     child1: [{name: "google", check: false}, 
       {name: "yahoo", check: false}, {name: "msn", check: false}],
     child2: [{name: "google", check: false}, {name: "yahoo", check: false}],        
};

var Object2 = {
    child1: [{name: "google", check: true}, {name: "yahoo", check: true}],
};

我想用Object2 Child1数组代替Object1 Child1数组,但不删除Object2中不存在的属性。

const NewObject = Object.assign({}, Object1, Object2)

上面的代码仅给我NewObject Object2。我正在查看的最终输出是在主对象中替换第二个对象的check true属性的地方。

var Object3 = {    
         child1: [{name: "google", check: true}, 
           {name: "yahoo", check: true}, {name: "msn", check: false}],
         child2: [{name: "google", check: false}, {name: "yahoo", check: false}],        
};      

5 个答案:

答案 0 :(得分:2)

此处的大多数答案基于以下事实:属性child1中的元素具有相同名称的相同索引。如果不是这种情况,让我为您提供另一种选择。此解决方案根据 name 而不是数组索引匹配child1中的元素。

var Object1 = {child1: [{name: "google", check: false}, {name: "yahoo", check: false}, {name: "msn", check: false}], child2: [{name: "google", check: false}, {name: "yahoo", check: false}]};
var Object2 = {child1: [{name: "yahoo", check: true}, {name: "google", check: true}]};
//                                ^                             ^
// I swapped the elements of Object2.child1 around to better show the
// intention of this specific solution.

function customAssign(obj1, obj2) {
  var result = {};

  // based on the fact that obj2 has a subset of keys of obj1
  Object.getOwnPropertyNames(obj1).forEach(key => {
    var attr1 = obj1[key], 
        attr2 = obj2[key], 
        itemLookup = {};

    if (Array.isArray(attr1) && Array.isArray(attr2)) {
      // based on the fact that the collection of an attribute
      // of obj2 a subset of the same attribue at obj1
      attr2.forEach(item => itemLookup[item.name] = item);
      result[key] = attr1.map(item1 => {
        var item2 = itemLookup[item1.name];
        if (item2 && item2.check) return item2;
        return item1;
      });
    } else {
      result[key] = attr2 || attr1;
    }
  });

  return result;
}

console.log(
  customAssign(Object1, Object2)
);

此解决方案仍然有一些限制。现在基于Object2具有Object1密钥子集的事实。此外,如果Object1Object2都具有数组属性,则Object2属性中存在的元素必须是Object1属性中存在的元素的子集(基于< em> name )。最后,Object2中的数组集合中的两个(或多个)项目可能没有相同的名称,如果确实发生,则使用两者中的较晚版本。

我希望以上内容能给您一些启发,即使这不是您要寻找的确切解决方案。

答案 1 :(得分:0)

我认为您正在寻找Lodash中的合并功能。或者,您可以构建自己的函数以递归方式合并对象,但最终结果将与Lodash实现的功能非常相似。

答案 2 :(得分:0)

您快到了,只需使用for..in来迭代Object1并检查Object2是否具有相同的键。如果它具有与child1类似的密钥,请使用Object.assign。注意,在Object.assign中,公共键的值将根据对象的顺序进行更新。例如,在Object.assign({}, Object1[keys], Object2[keys])中,它将使用来自Object1和Object2的键和值创建一个新对象,但是如果这两个对象之间有一个公共键,则Object2中keys的值将更新其中的相同键。 Object1

var Object1 = {
  child1: [{
      name: "google",
      check: false
    },
    {
      name: "yahoo",
      check: false
    }, {
      name: "msn",
      check: false
    }
  ],
  child2: [{
    name: "google",
    check: false
  }, {
    name: "yahoo",
    check: false
  }],
};

var Object2 = {
  child1: [{
    name: "google",
    check: true
  }, {
    name: "yahoo",
    check: true
  }],
};
let Object3 = {};

for (let keys in Object1) {
  if (Object2.hasOwnProperty(keys)) {
    Object3[keys] = Object.assign({}, Object1[keys], Object2[keys])
  } else {
    Object3[keys] = Object.assign({}, Object1[keys])
  }
}
console.log(Object3)

答案 3 :(得分:0)

使用lodashmerge功能,

var Object1 = {    
     child1: [{name: "google", check: false}, 
       {name: "yahoo", check: false}, {name: "msn", check: false}],
     child2: [{name: "google", check: false}, {name: "yahoo", check: false}],        
};

var Object2 = {
    child1: [{name: "google", check: true}, {name: "yahoo", check: true}],
};

_.merge(Object1, Object2);
console.log(Object1);

jsfiddle

答案 4 :(得分:0)

您都可以使用lodash或使用spread operator,可以执行以下操作:

var Object3 = {
    child1: [...Object2.child1],
    child2: [...Object1.child2],
};