JavaScript 对象合并

Posted 忧郁的蛋~

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JavaScript 对象合并相关的知识,希望对你有一定的参考价值。

javascript 中有多种方法可以合并对象。

1、使用 Object.assign() 方法:

它可以将一个或多个对象的属性复制到目标对象中。例如:

const obj1 =  a: 1, b: 2 ;
const obj2 =  b: 3, c: 4 ;
const obj3 = Object.assign(, obj1, obj2);
console.log(obj3); //  a: 1, b: 3, c: 4 

 

这里我们使用空对象()作为第一个参数,避免直接修改第一个对象。

2、使用解构赋值语法:

这种方法会在合并对象时保留键值相同的对象的属性,例如:

const obj1 =  a: 1, b: 2 ;
const obj2 =  b: 3, c: 4 ;
const obj3 =  ...obj1, ...obj2 ;
console.log(obj3); //  a: 1, b: 3, c: 4 

 

这里使用了扩展运算符,可以将一个对象的属性解构到另一个对象中。

3、使用 Lodash 中的 merge() 方法:

const obj1 =  a: 1, b: 2 ;
const obj2 =  b: 3, c: 4 ;
const obj3 = _.merge(obj1, obj2);
console.log(obj3); //  a: 1, b: 3, c: 4 

 4、for-in 循环 + 手动赋值:

const obj1 =  a: 1, b: 2 ;
const obj2 =  b: 3, c: 4 ;
const obj3 = ;
for (const key in obj1) 
  obj3[key] = obj1[key];

for (const key in obj2) 
  obj3[key] = obj2[key];

console.log(obj3); //  a: 1, b: 3, c: 4 

 5、使用 Object.keys() 和 Array.forEach() 方法:

const obj1 =  a: 1, b: 2 ;
const obj2 =  b: 3, c: 4 ;
const obj3 = ;
Object.keys(obj1).forEach(key => 
  obj3[key] = obj1[key];
);
Object.keys(obj2).forEach(key => 
  obj3[key] = obj2[key];
);
console.log(obj3); //  a: 1, b: 3, c: 4 

 

最后需要提醒的是,在合并对象时如果键值相同的对象属性类型不同,例如一个为字符串类型,一个为数值类型,会覆盖之前的属性,因此需要根据项目需求做出相应的处理。

此外,如果需要对合并对象的属性进行特殊处理,例如合并对象的属性值是一个数组,需要合并成一个新数组,可以使用 Array.concat() 方法。

const obj1 =  a: [1, 2] ;
const obj2 =  a: [3, 4] ;
const obj3 = Object.assign(, obj1, 
  a: obj1.a.concat(obj2.a)
);
console.log(obj3); //  a: [1, 2, 3, 4] 

 或者使用扩展运算符

const obj1 =  a: [1, 2] ;
const obj2 =  a: [3, 4] ;
const obj3 = ...obj1, a: [...obj1.a, ...obj2.a]
console.log(obj3); //  a: [1, 2, 3, 4] 

 此外,如果需要对合并对象的属性值进行进一步的处理,如去重、排序等,可以使用 Array.filter()、Array.sort() 等方法。

在 JavaScript 中合并两个对象(NodeList)数组

【中文标题】在 JavaScript 中合并两个对象(NodeList)数组【英文标题】:Merging two object (NodeList) arrays in JavaScript 【发布时间】:2013-01-17 21:16:52 【问题描述】:

我正在尝试合并两个对象数组,以便验证表单。在这种情况下,通常的 concat 方法似乎不起作用。 Concat 适用于普通的数值和字符串数组,但不适用于对象数组。 var allTags = allInputs.concat(allSelects); 行不行。

var allInputs = document.getElementsByTagName("input");
alert("Inputs: " + allInputs.length);

var allSelects = document.getElementsByTagName("select");
alert("Selects: " + allSelects.length);

var allTags = allInputs.concat(allSelects);
alert("allTags: " + allTags.length);

【问题讨论】:

这不是数组,它的数组像对象(NodeList) 其实就是一个NodeList,所以没有concat方法。 【参考方案1】:

Concat 适用于普通数值和字符串数组,但不适用于对象数组。

实际上是这样,但是NodeList 实例没有concat 方法,并且Array#concat 没有办法识别您想要展平这些(因为它们不是数组)。

但它仍然很容易做到(不过,请参阅下面的警告)。更改此行:

var allTags = allInputs.concat(allSelects);

var allTags = [];
allTags.push.apply(allTags, allInputs);
allTags.push.apply(allTags, allSelects);

Live Example | Source

这通过使用一点技巧来工作:Array#push 接受可变数量的元素添加到数组中,Function#apply 使用给定的 this 值调用函数(在我们的例子中,@987654335 @) 和任何类似数组的对象作为要传递给它的参数。由于NodeList 实例是类似数组的,push 很乐意将列表的所有元素推送到数组中。

Function#apply 的这种行为(不需要第二个参数真的是一个数组)在规范中非常明确定义,并且在现代浏览器中得到很好的支持。

遗憾的是,IE6 和 7 不支持上述内容(我认为它专门使用主机对象——NodeLists——作为Function#apply 的第二个参数),但是我们不应该支持它们,要么。 :-) IE8 也没有,这更有问题。 IE9 对此很满意。

如果您需要支持 IE8 及更早版本,可悲的是,我认为您会遇到一个无聊的旧循环:

var allInputs = document.getElementsByTagName('input');
var allSelects = document.getElementsByTagName('select');
var allTags = [];

appendAll(allTags, allInputs);
appendAll(allTags, allSelects);

function appendAll(dest, src) 
  var n;

  for (n = 0; n < src.length; ++n) 
    dest.push(src[n]);
  

  return dest;

Live Example | Source

确实适用于 IE8 及更早版本(以及其他)。

【讨论】:

@user2035797:不用担心,我现在还添加了一个适用于 IE8 及更早版本的示例。【参考方案2】:

document.get[something] 返回一个NodeList,它看起来与Array 非常相似,但有许多与众不同的特点,其中两个是:

不包含concat方法 项目列表实时。这意味着它们会随着文档的实时变化而变化。

如果您在将 NodeList 转换为实际数组时没有任何问题,您可以执行以下操作来达到您想要的效果:

var allInputs  = document.getElementsByTagName("input")
  , allSelects = document.getElementsByTagName("select")
;//nodeLists

var inputList  = makeArray(allInputs)
  , selectList = makeArray(allSelects)
;//nodeArrays

var combined   = inputList.concat(selectList);

function makeArray(list)
  return Array.prototype.slice.call(list);

您将失去原始 NodeList 的所有行为,包括它能够实时更新以反映对 DOM 的更改,但我的猜测是,这不是一个真正的问题。

【讨论】:

请注意,就像我在回答的第一部分中给出的类似解决方案一样,这在 IE8 或更早版本中不起作用。 (在这里试试:jsbin.com/iledok/1)sigh 至少 IE9 还不错。所以对于 IE8 及更早版本,需要一个无聊的旧循环。【参考方案3】:

您正在处理的是HTMLCollections,它们是实时集合(即,当您将节点添加到 DOM 时,它会自动添加到集合中。

遗憾的是,它没有concat 方法……这是有原因的。您需要做的是将其转换为数组,从而失去其实时行为:

var allInputsArray = [].slice.call(allInputs),
    allSelectsArray = [].slice.call(allSelects),
    allFields = allInputsArray.concat(allSelectsArray);

【讨论】:

【参考方案4】:

我找到了一种按 dom 对象在页面或表单中出现的顺序收集它们的简单方法。 首先,在对象上创建一个虚拟类样式“reqd”,然后使用以下内容按照它们在页面上出现的顺序创建一个列表。只需将类添加到您希望收集的任何对象。

var allTags = document.querySelectorAll("input.reqd, select.reqd");

【讨论】:

【参考方案5】:

查看过 underscore.js 吗?你可以这样做

 var allSelectsAndInputs = _.union(_.values(document.getElementsByTagName("input")),_.values(document.getElementsByTagName("select")));

欲了解更多信息,请参阅:http://underscorejs.org/#extend

该函数适用于对象,但在此设置中有效。

【讨论】:

实际上,我正在玩它……它似乎有点不对劲。待命。 如果您喜欢,请考虑对我的回答进行投票。

以上是关于JavaScript 对象合并的主要内容,如果未能解决你的问题,请参考以下文章

javascript实现一个合并多个对象的方法

如何将 JavaScript 类实例与对象合并?

在 JavaScript 中合并两个对象(NodeList)数组

如何合并嵌套对象Javascript? [复制]

Javascript合并并组合具有相同ID的对象

JavaScript - 如何合并/附加到对象/数组 - ReactJS - 传播语法