理由
const target = Object.assign({}, obj);
Object.assign
は、ディープコピーではなく、シャローコピーのため下階層のオブジェクトはコピーされない。
const target = Object.assign({}, obj);
Object.assign
は、ディープコピーではなく、シャローコピーのため下階層のオブジェクトはコピーされない。
汎用的な対応は自前で実装するのはコストが高いのでライブラリを使用する(自前の実装で解決できるレベルのネストであれば、ループなどで代入していくと良い)。
ディープコピーに関するライブラリはいくつか存在する。
この中でもパフォーマンスの高いらしいfast-copyを利用する。
import copy from "fast-copy";
const obj = {
nested: {
foo: true,
bar: false,
},
};
const target = copy(obj);
JSON.parse(JSON.stringify())
を利用するライブラリを使わずJSON.parse(JSON.stringify())
を使ったディープコピーの手法も存在する。
しかしながら、Object
をJSON.stringify()
で変換するとfunction
やキーがundefined
などの値が欠落してしまう。これを利用する場合はかなり限定的なObject
を対象とするしかない。
structuredClone()
を利用するモダンブラウザであればstructuredClone()
が利用できる。
const myDeepCopy = structuredClone(myOriginal);
深くネストされたデータのコピーが可能
多くの型をサポート(Map
/Set
/Regex
)
const obj = {
map: new Map(),
set: new Set(),
regex: /hi/,
object: { array: [] },
};
obj.circular = obj;
const deepCopy = structuredClone(obj);
循環参照もサポート
// Create an object with a value and a circular reference to itself.
const original = { name: "MDN" };
original.itself = original;
// Clone it
const clone = structuredClone(original);
console.assert(clone !== original); // the objects are not the same (not same identity)
console.assert(clone.name === "MDN"); // they do have the same values
console.assert(clone.itself === clone); // and the circular reference is preserved