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 の型をサポートしています。

プリミティブ値(文字列、数値、真偽値、null、undefined)
Date
RegExp
Map / Set
ArrayBuffer / TypedArray
Blob / File

コピーできないもの

ただし、すべての値がコピーできるわけではありません。以下の値を含むオブジェクトはエラーになります。

関数

関数を含むオブジェクトはコピーできません。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() の使用を検討するのがおすすめです。