はじめに
こんにちは。アメリカ在住で独学エンジニアを目指している Taira です。
JavaScript で「オブジェクトをコピーしたい」と思ったことはありませんか?
単純に代入すると参照が共有されてしまい、浅いコピー(スプレッド構文など)ではネストしたデータが壊れてしまいます。
そんなときに使えるのが、structuredClone。
これは 標準で使える「ディープコピー関数」 です。
結論
-
structuredCloneを使うと、オブジェクトを安全にディープコピーできる -
JSON.stringify/parseでは失われる型(Date,Map,Set, etc.)も正しくコピーできる
基本的な使い方
const original = {
name: 'Taira',
hobbies: ['coding', 'gym'],
date: new Date(),
};
const copy = structuredClone(original);
copy.hobbies.push('travel');
console.log(original.hobbies); // ["coding", "gym"] ← 影響なし!
JSON.stringify との違い
const obj = { date: new Date(), set: new Set([1, 2]) };
// JSON だと Date は文字列化、Set は失われる
const jsonCopy = JSON.parse(JSON.stringify(obj));
console.log(jsonCopy); // { date: "2025-09-08T12:00:00.000Z" }
// structuredClone ならそのままコピーできる
const clone = structuredClone(obj);
console.log(clone.date instanceof Date); // true
console.log(clone.set instanceof Set); // true
なぜ structuredClone が必要か?(自作の useState の様な関数を作った例)
const makeOnChangeHarness = (initial: Draft) => {
// 初期値をクローンして state として保持
let state = structuredClone(initial);
const onChange = (updater: Draft | ((prev: Draft) => Draft)) => {
state = typeof updater === 'function' ? updater(state) : updater;
};
return { onChange, get: () => state };
};
setValue({ name: 'Taira' }); // 値をそのまま渡すパターン
setValue((prev) => ({ ...prev, name: 'Taira' })); // updater関数パターン
❌ structuredClone を使わないと…
let state = initial;
state.nested.a = 99;
console.log(initial.nested.a); // 99 ← 初期値まで壊れた
✅ structuredClone を使うと…
let state = structuredClone(initial);
state.nested.a = 99;
console.log(initial.nested.a); // 1 ← 初期値は守られた
React の useState も「初期値は固定して、その後の state 更新は独立して行える」仕組みです。
それを模したこのコードでは、structuredClone がなければ initial を安全に守れません。
まとめ
-
structuredCloneは 「安全にディープコピーするための標準関数」 - ネストしたオブジェクトや
Date,Map,Setもコピーできる -
useStateのように「初期値を壊したくない場面」でとても便利