浅いマージではなく深いマージを行うにはどうすればいいですか? 質問する

浅いマージではなく深いマージを行うにはどうすればいいですか? 質問する

両方オブジェクト.割り当てそしてオブジェクトの拡散浅いマージのみを実行します。

問題の例:

// 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 } }

スプレッド構文は 1 レベルの深さまでしか行わないため、 x は完全に上書きされます。 の場合も同様ですObject.assign()

これを実行する方法はありますか?

ベストアンサー1

これは少し古い問題だとは思いますが、ES2015/ES6で私が思いついた最も簡単な解決策は、Object.assign()を使用するという非常にシンプルなものでした。

これがお役に立てば幸いです:

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

/**
 * Deep merge two objects.
 * @param target
 * @param ...sources
 */
export function mergeDeep(target, ...sources) {
  if (!sources.length) return target;
  const source = sources.shift();

  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 mergeDeep(target, ...sources);
}

使用例:

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] } } }

この不変バージョンは、以下の回答に記載されています。

これは循環参照の無限再帰につながることに注意してください。この問題に直面する可能性があると思われる場合は、循環参照を検出する方法についての優れた回答がここにあります。

おすすめ記事