将两个JavaScript对象合并为一个?

21

我尝试将以下对象合并为一个对象,但迄今为止没有成功-在我的console.log中结构如下:

    2018-05-11 : {posts: 2} // var posts
    2018-05-11 : {notes: 1} // var notes

合并后,我希望它看起来像下面这样

2018-05-11 : {posts: 2, notes: 1}

我尝试过使用object.assign(),但它只是删除了初始帖子数据 - 有什么更好的方法吗?


Object.assign 应该可以工作。如果你想将 b 添加到 a 中,请使用 Object.assign( a, b )。如果你想将 a 和 b 都添加到一个新对象中,请使用 Object.assign( {}, a, b )。你能展示一下你尝试过的 Object.assign() 代码吗? - Shilly
你看过这个问题吗? - Federico klez Culloca
请记住,keys是唯一的。像这样循环遍历它非常容易。 - deEr.
1
@stdob - 也就是说,这个问题与建议链接中的重复问题不同,因为每个对象都具有相同的索引,这会由于浅拷贝而产生问题。 - Wancieho
如果Zabs提供了他尝试过的代码片段(没有达到他想要的效果),那么这个问题就会更清晰(并且更明显不是重复的)。 根据被采纳的答案和他在使用object.assign时出错的描述,似乎他将“2018-05-11:{posts:2}”读入JavaScript作为类似于“{'2018-05-11':{posts:2}}”的对象。 尝试合并两个这样的对象,然后遇到assign是浅拷贝的问题。 - ToolmakerSteve
嗯。在建议的重复内容中继续向下阅读,我看到有答案描述如何进行深度合并(具有相同键的对象)。请参见https://dev59.com/MHVC5IYBdhLWcg3w1E1q#383245和其他答案。因此,我的重新打开提案可以被忽略。(最初,像Wancieho一样,我以为其他问答只讨论了*浅层合并*。) - ToolmakerSteve
6个回答

16

var x =  {posts: 2};
var y = {notes: 1};
var z = Object.assign( {}, x, y );
console.log(z);

使用 Object.assign() 将对象属性分配给空对象。

1
这完全与他所要求的结果不符。 - Wancieho
@Wancieho,根据OP所要求的结果,你说得完全正确。但是你假设了一个未经证实的数据结构。MayK的答案也是正确的,但至少说明了它适用于哪种数据结构。 - Auspex
1
@Auspex 嗯,你有看过这个答案的输出和 OP 想要的吗?这个答案缺少了 2018-05-11 键。 - Wancieho
3
不要侮辱别人。事实上,原帖并没有说日期是关键,它说这些是“日志”记录。你只是自作聪明地做出了假设。我不是那个没有读清问题的人。 - Auspex
从OP的陈述“我已经尝试了object.assign(),但它只是删除了最初的帖子数据”可以推断出他有两个具有相同键的对象。因此,这个答案对他或任何有类似症状的人都没有帮助。 - ToolmakerSteve

4

You can do the following with Object.assign():

var posts = {'2018-05-11' : {posts: 2}} // var posts
var notes = {'2018-05-11' : {notes: 1}} // var notes

Object.assign(posts['2018-05-11'], notes['2018-05-11']);
console.log(posts);


请注意,此操作不执行深度合并。 - Peter Tseng

4

这里有一个更通用的函数。它会遍历整个对象并将内容合并到已声明的变量中。

const posts = {  '2018-05-11': {    posts: 2  },  '2018-05-12': {    posts: 5  }};
const notes = {  '2018-05-11': {    notes: 1  },  '2018-05-12': {    notes: 3  }};

function objCombine(obj, variable) {
  for (let key of Object.keys(obj)) {
    if (!variable[key]) variable[key] = {};

    for (let innerKey of Object.keys(obj[key]))
      variable[key][innerKey] = obj[key][innerKey];
  }
}

let combined = {};
objCombine(posts, combined);
objCombine(notes, combined);
console.log(combined)

希望这对您有所帮助。


注意:这既不是浅合并也不是深合并。我不确定确切的术语,但它比浅合并“深一层”。对于OP的问题来说足够了。深度等效将递归:用objCombine(obj [key],variable [key])替换以for(let innerkey ...开头的两行。我认为-没有测试过。 - ToolmakerSteve

3
你可以使用 Lodash 库的 merge 方法。

const posts = {'2018-05-11' : {posts: 2}}
const notes = {'2018-05-11' : {notes: 1}}

const result = _.merge({}, posts, notes);
console.log(result)
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.10/lodash.js"></script>


1
我倾向于使用lodash,因为它在处理像其中一个对象不是对象这样的情况时提供了防御性,并防止出现令人讨厌的js错误... - random_user_name
@nenad 安装一个库来使用原生JS执行某些操作?我觉得不需要... - Wancieho
@Wancieho 没有人建议安装库。事实上,我们大多数人都在使用库,很多人正在使用lodash。如果您也在使用它,那么像cale_b建议的那样使用merge可能是值得的。 - Auspex
@Auspex 安装/嵌入或者你想怎么称呼它,这都是不必要的开销。提供需要另一个不必要依赖的解决方案是不正确的。没有什么可争论的。 - Wancieho
如果您已经有了lodash,那么就没有额外的开销。SO旨在获取尽可能多的答案,而不是一个理论上正确的答案。是的,没有证据表明这是最适合OP的答案,但我保证它将是对一些人来说最好的答案。 - Auspex

2
您需要像这样为每个项目应用assign:

var a =  {"2018-05-11" : {notes: 1}};

var b =  {"2018-05-11" : {posts: 3}};

var result = {};

Object.keys(a).forEach(k=>{result[k] = Object.assign(a[k],b[k])});

console.log(result);


1

jQuery.extend() 可能会有帮助。

默认情况下,$.extend() 执行的合并不是递归的;如果第一个对象的属性本身就是一个对象或数组,则它将被第二个或后续对象中具有相同键的属性完全覆盖。值不会合并。但是,通过为第一个函数参数传递 true,对象将递归合并。

试试

$.extend(obj1, obj2)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接