Code Fix

中級

スプレッド構文{ ...obj }はネストした値までは複製しない(浅いコピー)

{ ...obj }や[...arr]は最上位のプロパティだけをコピーします。値がオブジェクトや配列の場合、コピー先とコピー元は同じ参照を共有したままです。

なぜエラーが出ないのか

出力: Osaka
(エラーなし)
JavaScriptは何も報告しません。文法として正しいためです
出力: Osaka
実際の挙動 — 期待した結果と食い違っている箇所
見つけ方
エラーが出ないので、出力を目で確かめるか、コードを目で追うしかありません。この種の誤りが最も発見が遅れます

このエラーが出る典型パターン

パターン1

 1  const original = { name: "Al", address: { city: "Tokyo" } };
 2  const copy = { ...original }          ;
                             ^
 3  copy.address.city = "Osaka";
 4  console.log(original.address.city);
出力: Osaka期待: Tokyo (エラーにはなりません)

スプレッド構文は最上位のプロパティしかコピーしません。addressオブジェクトは元と同じ参照のままなので、コピー先を変更すると元のデータも変わります。structuredClone()は深いコピーになります。

直し方: { ...original }structuredClone(original) にします。

この問題を解いてみる →

広告
広告スロット(未設定)

パターン2

 1  const users = [{ name: "Al" }];
 2  const copy = [...users]            ;
                            ^
 3  copy[0].name = "Bo";
 4  console.log(users[0].name);
出力: Bo期待: Al (エラーにはなりません)

配列のスプレッドも要素自体(オブジェクト)はコピーせず参照をコピーします。要素の中身まで独立させたい場合はstructuredClone()を使います。

直し方: [...users]structuredClone(users) にします。

この問題を解いてみる →

パターン3

 1  const state = { tags: ["a", "b"] };
 2  const copy = { ...state }          ;
                            ^
 3  copy.tags.push("c");
 4  console.log(state.tags.length);
出力: 3期待: 2 (エラーにはなりません)

tagsプロパティは配列という参照型なので、スプレッドでコピーしても同じ配列を共有したままです。コピー先へのpushが元のstateにも反映されてしまいます。

直し方: { ...state }structuredClone(state) にします。

この問題を解いてみる →

よくある誤解

「スプレッド構文でコピーしたから元のデータは安全」とは限りません。ネストしたオブジェクト・配列は参照がそのままコピーされるため、コピー先を変更すると元のデータも変わってしまいます。

まとめ

スプレッド構文{ ...obj }はネストした値までは複製しない(浅いコピー)は中級でつまずきやすい項目です。上の3パターンを実際に手で直すと、エラーメッセージのどこを読めばよいかが掴めます。

演習をはじめる

関連するエラー

広告
広告スロット(未設定)