两个对象。assign和Object spread只做浅合并。

这个问题的一个例子:

// No object nesting
const x = { a: 1 }
const y = { b: 1 }
const z = { ...x, ...y } // { a: 1, b: 1 }

输出是您所期望的。然而,如果我尝试这样做:

// Object nesting
const x = { a: { a: 1 } }
const y = { a: { b: 1 } }
const z = { ...x, ...y } // { a: { b: 1 } }

而不是

{ a: { a: 1, b: 1 } }

你得到

{ a: { b: 1 } }

X被完全覆盖,因为扩展语法只覆盖了一层。这与Object.assign()相同。

有办法做到这一点吗?


当前回答

这是一个廉价的深度合并,使用尽可能少的代码我能想到。当前一个属性存在时,每个源都会覆盖它。

const { keys } = Object;

const isObject = a => typeof a === "object" && !Array.isArray(a);
const merge = (a, b) =>
  isObject(a) && isObject(b)
    ? deepMerge(a, b)
    : isObject(a) && !isObject(b)
    ? a
    : b;

const coalesceByKey = source => (acc, key) =>
  (acc[key] && source[key]
    ? (acc[key] = merge(acc[key], source[key]))
    : (acc[key] = source[key])) && acc;

/**
 * Merge all sources into the target
 * overwriting primitive values in the the accumulated target as we go (if they already exist)
 * @param {*} target
 * @param  {...any} sources
 */
const deepMerge = (target, ...sources) =>
  sources.reduce(
    (acc, source) => keys(source).reduce(coalesceByKey(source), acc),
    target
  );

console.log(deepMerge({ a: 1 }, { a: 2 }));
console.log(deepMerge({ a: 1 }, { a: { b: 2 } }));
console.log(deepMerge({ a: { b: 2 } }, { a: 1 }));

其他回答

你可以使用Lodash合并:

Var对象= { 'a': [{'b': 2}, {'d': 4}] }; Var other = { 'a': [{'c': 3}, {'e': 5}] }; console.log(_。合并(对象,其他)); / / = > {a: [{b: 2,“c”:3},{' d ': 4,“e”:5}]} < script src = " https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.21/lodash.min.js " > < /脚本>

我们可以使用$.extend(true,object1,object2)进行深度合并。值true表示递归合并两个对象,修改第一个对象。

美元扩展(真的,目标,对象)

我在加载缓存redux状态时遇到了这个问题。如果我只是加载缓存的状态,我会遇到错误的新应用程序版本与更新的状态结构。

前面已经提到过,lodash提供了merge函数,我使用了这个函数:

const currentInitialState = configureState().getState();
const mergedState = _.merge({}, currentInitialState, cachedState);
const store = configureState(mergedState);

有一些维护良好的库已经做到了这一点。npm注册表中的一个例子是merge-deep

它不存在,但你可以使用JSON.parse(JSON.stringify(jobs))