JavaScriptのオブジェクトをコピーする方法(スプレッド構文・Object.assign)
生徒
「先生、JavaScriptのオブジェクトを別の変数にコピーしたいんですけど、どうすればいいですか?」
先生
「コピーの方法にはいくつかありますが、初心者におすすめなのはスプレッド構文とObject.assignを使う方法です。」
生徒
「スプレッド構文ってなんですか?それにObject.assignって初めて聞きました…」
先生
「順番に分かりやすく説明していきましょう!」
1. JavaScriptのオブジェクトとは?
まず、オブジェクトとは、複数の情報(プロパティ)をひとつにまとめたデータのことです。名前や年齢、職業などの情報をセットで持たせることができます。
const person = {
name: "田中",
age: 28,
job: "デザイナー"
};
このpersonオブジェクトを、そっくりそのまま別の変数にコピーしたいときに使えるのが、今回紹介する「スプレッド構文」と「Object.assign」です。
2. スプレッド構文(...)でコピーする方法
スプレッド構文とは、オブジェクトの中身を「展開」して取り出す記法です。コピーしたいときには以下のように使います。
const copyPerson = { ...person };
このように書くと、personの中身をすべて取り出してcopyPersonという新しいオブジェクトにコピーします。
確認のため、コピー後のオブジェクトを表示してみましょう。
console.log(copyPerson);
{name: "田中", age: 28, job: "デザイナー"}
スプレッド構文はシンプルで書きやすく、初心者にも扱いやすい方法です。
3. Object.assignでコピーする方法
Object.assignは、JavaScriptの標準のメソッド(関数のようなもの)です。オブジェクトを別のオブジェクトにコピーするときに使います。
const copyPerson2 = Object.assign({}, person);
この例では、最初の{}が空のオブジェクトです。そこにpersonの中身をコピーして、新しいcopyPerson2を作っています。
結果を見てみましょう。
console.log(copyPerson2);
{name: "田中", age: 28, job: "デザイナー"}
4. 代入だけではコピーにならない理由
初心者がよくやってしまう間違いが、オブジェクトを=で代入してコピーしようとすることです。たとえば次のようなコードです。
const wrongCopy = person;
これはコピーではなく、「同じものを指しているだけ」になります。wrongCopyを変更すると、personまで変更されてしまいます。
wrongCopy.age = 35;
console.log(person.age);
35
このように、単純な代入では別のコピーにはならないので注意が必要です。
5. 浅いコピーと深いコピーの違い
ここまで紹介してきた方法(スプレッド構文・Object.assign)は「浅いコピー」と呼ばれます。浅いコピーとは、オブジェクトの中にオブジェクトがある場合、その中まではコピーされず、参照だけがコピーされるという意味です。
const book = {
title: "JavaScript入門",
author: {
name: "佐々木",
age: 40
}
};
const shallowCopy = { ...book };
shallowCopy.author.age = 50;
console.log(book.author.age);
50
このように、ネストされた中身まではコピーされず、元のオブジェクトも一緒に変わってしまいます。本格的なコピーが必要なときは、別の方法が必要になりますが、まずは浅いコピーを理解することが重要です。
まとめ
ここまで学んできた内容を振り返ると、JavaScriptのオブジェクトをコピーする方法にはいくつもの重要な考え方が含まれていることがよくわかります。特に、実際の開発場面ではオブジェクトを安全に取り扱う場面が多く、意図せず元のデータを書き換えてしまうと、予期しない不具合に繋がることがよくあります。そのため、オブジェクトのコピーという一見単純に見える操作でも、丁寧に理解しておくことはとても大切です。今回取り上げたスプレッド構文やObject.assignは、実務でも頻繁に利用される基本的な方法であり、扱いに慣れておくと後々とても役に立ちます。特にスプレッド構文は簡潔で読みやすく、初学者から上級者まで幅広く利用されているため、積極的に活用する練習をしておくとよいでしょう。また、Object.assignは複数のオブジェクトをまとめる場面でも使えるため、応用性が高く便利です。
一方で、浅いコピーと深いコピーの違いは、初心者がつまずきやすい重要な概念です。浅いコピーでは、ひとつ上の階層まではコピーされますが、その中にさらにオブジェクトが入っている場合には参照が共有される点が特徴です。この性質を理解していないと、予想外の値が書き換わってしまい、思った通りの動作にならないことが起きてしまいます。特に大規模なデータや複雑な設定を扱うアプリケーションでは、この浅いコピーと深いコピーの違いを理解しておくことで、安全にデータを扱うことができます。
スプレッド構文とObject.assignの違いを整理しよう
スプレッド構文は、視覚的にもシンプルで、直感的にコピーの意図が伝わるため、コードを読む人にも親切な書き方です。基本的には以下のように一行でまとめることができます。
const copied = { ...original };
一方でObject.assignを使った方法は、複数のオブジェクトをまとめるときに効果を発揮します。
const copied = Object.assign({}, original);
どちらの方法でも浅いコピーが行われる点は同じですが、コードの書き方や用途に応じて使い分けることで、読みやすさや保守性がぐっと向上します。日常の学習の中でも、意識的に使い分けを試してみると、理解がより深まるでしょう。
浅いコピーと深いコピーの影響を理解する
浅いコピーがどのような動作をするかを理解するには、具体的な例を見ることが一番です。以下のコードでは、ネストされたオブジェクトがどう扱われるかがよくわかります。
const item = {
info: {
name: "参考書",
price: 1200
}
};
const shallow = { ...item };
shallow.info.price = 1500;
console.log(item.info.price);
この例では、shallowの中のpriceを変更すると、元のitem側のpriceも書き換わってしまいます。これは参照が共有されているためであり、浅いコピーの典型的な動作です。値が大きく変わってしまうようなケースでは、さらに深い部分までコピーする方法を検討する必要があります。
安全にデータを扱う第一歩
今回学んだ内容を通して、JavaScriptでオブジェクトを扱う際の基本的な考え方が身についたはずです。スプレッド構文やObject.assignなどの便利な方法を活用しながら、自分が意図した通りにデータを扱えるようになると、より大きなプログラムに挑戦するときにも安心してコードを書くことができます。また、基本的なコピーの仕組みは、配列など他のデータ構造にも共通する考え方が多いため、今後の学習にもつながっていく大切なステップとなります。
生徒
「先生、オブジェクトのコピーってもっと簡単だと思ってましたけど、奥が深いんですね…!」
先生
「実際に使ってみると、浅いコピーと深いコピーの違いがとても大事だと感じる場面が多いんだよ。特に大きなデータを扱うほど、気をつけるべきポイントが増えていくんだ。」
生徒
「スプレッド構文が簡単で使いやすいのはわかりました!でも、ネストされたオブジェクトがあるときは注意しなきゃいけないんですね。」
先生
「そうだね。今回の例みたいに動きを確認しながら学んでいけば、自然と判断できるようになるよ。」
生徒
「もっといろいろな書き方を試してみたくなりました!次の学習も楽しみです。」