両方オブジェクト.割り当てそしてオブジェクトの拡散浅いマージのみを実行します。
問題の例:
// 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] } } }
この不変バージョンは、以下の回答に記載されています。
これは循環参照の無限再帰につながることに注意してください。この問題に直面する可能性があると思われる場合は、循環参照を検出する方法についての優れた回答がここにあります。