structuredClone と DOM 配列のコピー
structuredClone は構造化複製アルゴリズム(Structured Clone Algorithm)を使用してオブジェクトを再帰的にコピーする。JSON.parse/stringify と異なり、循環参照や特殊なオブジェクト型も扱える。
const original = {
name: 'test',
nested: { value: 42 },
date: new Date(),
arr: [1, 2, { deep: true }]
}
const cloned = structuredClone(original)
cloned.nested.value = 100
console.log(original.nested.value) // 42(元のオブジェクトは変更されない)DOM 要素と structuredClone
DOM 要素(Node オブジェクト)は structuredClone でコピーできない。これは構造化複製アルゴリズムの仕様上の制限である。
const div = document.createElement('div')
structuredClone(div) // DataCloneError: HTMLDivElement could not be clonedDOM 要素の配列についても同様で、配列自体はコピーできるが、中に DOM 要素が含まれていると例外が発生する。
const elements = [
document.createElement('div'),
document.createElement('span')
]
structuredClone(elements) // DataCloneErrorDOM 配列をコピーする方法
DOM 要素を含む配列をコピーしたい場合は、cloneNode メソッドを組み合わせる。
const elements = document.querySelectorAll('.item')
const elementsArray = Array.from(elements)
// 浅いコピー(参照のコピー)
const shallowCopy = [...elementsArray]
// 深いコピー(DOM 要素自体を複製)
const deepCopy = elementsArray.map(el => el.cloneNode(true))cloneNode(true) を使うと、要素とその子孫すべてが複製される。cloneNode(false) では要素自体のみが複製され、子要素は含まれない。
structuredClone でコピーできる型とできない型
プリミティブ値、Date、RegExp、ArrayBuffer、TypedArray、Map、Set、Blob、File、ImageData、配列、プレーンオブジェクト
Function、DOM ノード、Symbol、WeakMap、WeakSet、Error オブジェクト(一部環境)、プロパティディスクリプタ(getter/setter)
関数を含むオブジェクトをコピーしようとすると、同様に DataCloneError が発生する。
const obj = {
data: 'test',
method: function() { return this.data }
}
structuredClone(obj) // DataCloneError: function could not be cloned循環参照への対応
structuredClone は循環参照を正しく処理できる。これは JSON.stringify では不可能な操作である。
const obj = { name: 'circular' }
obj.self = obj
const cloned = structuredClone(obj)
console.log(cloned.self === cloned) // true(循環構造が維持される)
console.log(cloned !== obj) // true(別のオブジェクト)transferables オプション
structuredClone の第二引数で transfer オプションを指定すると、ArrayBuffer などの所有権を移転できる。
const buffer = new ArrayBuffer(1024)
const cloned = structuredClone(buffer, { transfer: [buffer] })
console.log(buffer.byteLength) // 0(元のバッファは使用不可に)
console.log(cloned.byteLength) // 1024これはコピーではなく移転なので、メモリ効率が良い。大きなバイナリデータを扱う際に有用。













