structuredClone() によるディープコピー
structuredClone() は、オブジェクトのディープコピーを作成するためのネイティブメソッドです。ES2022 で標準化され、現在の主要なブラウザと Node.js で利用できます。
基本的な使い方
structuredClone() にオブジェクトを渡すと、完全なディープコピーが返されます。
const original = {
name: "田中",
items: [1, 2, 3],
nested: {
city: "東京",
tags: ["a", "b"]
}
};
const copy = structuredClone(original);
copy.nested.city = "大阪";
console.log(original.nested.city); // "東京"(影響なし)JSON.parse(JSON.stringify()) との違い
従来よく使われていた JSON 変換によるディープコピーと比較すると、structuredClone() は多くの型を正しく扱えます。
| データ型 | JSON 方式 | structuredClone() |
|---|---|---|
| Date | 文字列になる | 正しくコピー |
| Map | 失われる | 正しくコピー |
| Set | 失われる | 正しくコピー |
const original = {
date: new Date('2024-01-01'),
map: new Map([['key', 'value']]),
set: new Set([1, 2, 3])
};
// JSON 方式
const jsonCopy = JSON.parse(JSON.stringify(original));
console.log(jsonCopy.date instanceof Date); // false
console.log(jsonCopy.map); // {}(空オブジェクト)
// structuredClone()
const cloned = structuredClone(original);
console.log(cloned.date instanceof Date); // true
console.log(cloned.map.get('key')); // "value"対応しているデータ型
structuredClone() は、以下のような多くの JavaScript の型をサポートしています。
コピーできないもの
ただし、すべての値がコピーできるわけではありません。以下の値を含むオブジェクトはエラーになります。
関数
関数を含むオブジェクトはコピーできません。DataCloneError が発生します。
DOM ノード
HTMLElement などの DOM ノードもコピーできません。
// エラーになる例
const withFunction = {
greet: function() { return "Hello"; }
};
try {
structuredClone(withFunction);
} catch (e) {
console.log(e.name); // "DataCloneError"
}循環参照の処理
structuredClone() は循環参照を持つオブジェクトも正しくコピーできます。JSON.stringify() では循環参照があるとエラーになりますが、structuredClone() は問題なく動作します。
const obj = { name: "test" };
obj.self = obj; // 循環参照
const copy = structuredClone(obj);
console.log(copy.self === copy); // true(循環構造も維持)ディープコピーが必要な場面では、まず structuredClone() の使用を検討するのがおすすめです。