如何在 ES6+ 中将两个 javascript 对象合并在一起?

IT技术 javascript ecmascript-6
2021-02-03 20:21:00

我厌倦了总是不得不编写这样的代码:

function shallowExtend(obj1,obj2){
  var key;
  for ( key in obj2 ) {
    if ( obj2.hasOwnProperty(key) === false )  continue;
    obj1[key] = obj2[key]
  }
}

或者,如果我不想自己编写代码,请实现一个已经这样做的库。ES6+ 肯定会在这方面提供帮助,这将为我们提供类似Object.prototype.extend(obj2...)Object.extend(obj1,obj2...)

那么 ES6+ 是否提供这样的功能呢?如果还没有,那么是否计划了此类功能?如果没有计划,那为什么不呢?

6个回答

您将能够使用 Object.assign 在 ES6 中进行浅层合并/扩展/分配:

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign

句法:

Object.assign(目标,来源);

其中...sources表示源对象。

例子:

var obj1 = {name: 'Daisy', age: 30};
var obj2 = {name: 'Casey'};

Object.assign(obj1, obj2);

console.log(obj1.name === 'Casey' && obj1.age === 30);
// true
请注意这是一个浅扩展...嵌套对象未合并
2021-03-16 20:21:00
有一种很好的方法可以在没有库的情况下使用 just 来合并深度嵌套的对象Object.assign请在此处查看我的答案
2021-03-21 20:21:00
一个小提示: Object.assign 会改变目标。如果这不是你想要的,你可以用一个空对象调用它:let merged = Object.assign({}, source1, source2);
2021-03-29 20:21:00
@monzonj,在不使用 lodash 或 mout 的情况下,是否没有任何选项可以扩展嵌套对象?
2021-04-02 20:21:00
扩展嵌套对象的一种旧方法是使用 JSON.parse(JSON.stringify(src))
2021-04-05 20:21:00

您可以为此使用对象传播语法

const merged = {...obj1, ...obj2}

对于数组,展开运算符已经是 ES6 (ES2015) 的一部分,但对于对象,它已添加到 ES9 (ES2018) 的语言规范中。它的提议在此之前很久就在 Babel 等工具中默认启用。

啊原谅我。你说的对。目前它是 babel 阶段 2 的功能。github.com/sebmarkbage/ecmascript-rest-spread我从来没有意识到这一点,因为我从一开始就在使用 babel 并默认启用它。但是因为无论如何你都需要转译,而且对象传播是一件非常简单的事情,我无论如何都会推荐它。我喜欢它。
2021-03-23 20:21:00
现在没有正式称为 ES2015 :P 从什么时候开始解构不是 ES6 的一部分?developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/... 运行 babel-node:const ob1 = {foo: 123}; const ob2 = {bar: 234}; const merged = {...ob1, ...ob2}; console.log(merged) 输出:{ foo: 123, bar: 234 }
2021-03-26 20:21:00
这不是解构,它是传播 - 不,对于对象,它不是 ES6 的一部分。您应该在 babel 中禁用实验性 ES7 草稿。
2021-03-31 20:21:00
注意:当相同的属性存在于两个obj1obj2,从最右边的(后者)对象优先的值(obj2
2021-04-01 20:21:00
“默认情况下启用第 2 阶段或更高阶段的提案”。babeljs.io/docs/usage/experimental
2021-04-04 20:21:00

我知道这是一个老问题,但 ES2015/ES6 中最简单的解决方案实际上非常简单,使用 Object.assign(),

希望这会有所帮助,这也可以进行深度合并:

/**
 * Simple is object check.
 * @param item
 * @returns {boolean}
 */
export function isObject(item) {
  return (item && typeof item === 'object' && !Array.isArray(item) && item !== null);
}

/**
 * Deep merge two objects.
 * @param target
 * @param source
 */
export function mergeDeep(target, source) {
  if (isObject(target) && isObject(source)) {
    for (const key in source) {
      if (isObject(source[key])) {
        if (!target[key]) Object.assign(target, { [key]: {} });
        mergeDeep(target[key], source[key]);
      } else {
        Object.assign(target, { [key]: source[key] });
      }
    }
  }
  return target;
}

用法示例:

mergeDeep(this, { a: { b: { c: 123 } } });
// or
const merged = mergeDeep({a: 1}, { b : { c: { d: { e: 12345}}}});  
console.dir(merged); // { a: 1, b: { c: { d: [Object] } } }

ES6

Object.assign(o1,o2) ; 
Object.assign({},o1,o2) ; //safe inheritance
var copy=Object.assign({},o1); // clone o1
//------Transform array of objects to one object---
var subjects_assess=[{maths:92},{phy:75},{sport:99}];
Object.assign(...subjects_assess); // {maths:92,phy:75,sport:99}

ES7 或 Babel

{...o1,...o2} // inheritance
 var copy= {...o1};
@FilipBartuzi 这不是您链接的 ES6。但它基本上相当于 lodash/underscore 中的 _.extend()。
2021-03-15 20:21:00

Object.mixin目前正在讨论照顾你所要求的行为。https://mail.mozilla.org/pipermail/es-discuss/2012-December/027037.html

虽然它还没有出现在 ES6 草案中,但似乎有很多人支持它,所以我认为它很快就会出现在草案中。

2021-03-17 20:21:00
警告- 此答案不再正确,请参阅 Jack 的答案以获取正确且有效的方法。
2021-03-28 20:21:00
Object.mixin 已被 Object.assign 取代
2021-04-09 20:21:00