[JavaScript] Object.assignでネストされたオブジェクトがコピーされない問題
2 min read
理由
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