JavaScriptの配列のコピー方法(スプレッド構文・slice)
生徒
「JavaScriptで配列を丸ごとコピーする方法ってありますか?元の配列を変えずに新しい配列を作りたいんです。」
先生
「はい、配列をコピーするには主に2つの方法がよく使われます。スプレッド構文とsliceメソッドです。どちらも元の配列を変えずに新しい配列を作ることができますよ。」
生徒
「スプレッド構文とかsliceって何ですか?難しそうですけど、できれば分かりやすく教えてください!」
先生
「もちろんです!それぞれ順番に説明していきましょう。」
1. スプレッド構文(...)とは?配列の中身を広げてコピーする
スプレッド構文は、配列の中身をバラバラにして、新しい配列に「広げる」記号です。見た目は「...」と3つの点が並んでいます。
たとえば、箱に入ったおもちゃがあるとして、その箱の中身を全部別の箱に移したい時、スプレッド構文は中身だけを取り出して新しい箱に入れるイメージです。
let fruits = ["りんご", "みかん", "バナナ"];
let copyFruits = [...fruits];
console.log(copyFruits); // ["りんご", "みかん", "バナナ"]
console.log(fruits === copyFruits); // false(別の配列なので違うと判定される)
このようにスプレッド構文を使うと、元の配列を変更せずに同じ内容の新しい配列を作れます。
2. sliceメソッドで配列をコピーする方法
slice()はもともと配列の一部分を切り出すためのメソッドですが、引数を何も指定しなければ配列全体をコピーできます。
箱から全部のおもちゃをそのまま別の箱に移すイメージですね。
let fruits = ["りんご", "みかん", "バナナ"];
let copyFruits = fruits.slice();
console.log(copyFruits); // ["りんご", "みかん", "バナナ"]
console.log(fruits === copyFruits); // false(別の配列なので違うと判定される)
slice()を使うと元の配列を変えずにコピーできます。引数なしで使うことがポイントです。
3. コピーした配列は元の配列と違うもの
コピーした配列は、元の配列とは別の「箱」なので、どちらかを変えてももう一方には影響しません。
let fruits = ["りんご", "みかん"];
let copyFruits = [...fruits];
copyFruits.push("バナナ");
console.log(fruits); // ["りんご", "みかん"]
console.log(copyFruits); // ["りんご", "みかん", "バナナ"]
このように、コピーした配列に新しい要素を追加しても元の配列には変化がありません。
4. コピーで注意したい「浅いコピー」とは?
今回紹介したスプレッド構文やsliceは「浅いコピー」と呼ばれます。これは、配列の中に別の配列やオブジェクトがある場合、それらの中身まではコピーされず、元のものと同じ参照(住所のようなもの)を指します。
たとえば、箱の中に小さな箱がある場合、その小さな箱はコピーされず、同じ箱を指してしまうイメージです。
let original = [1, 2, [3, 4]];
let copy = [...original];
copy[2].push(5);
console.log(original); // [1, 2, [3, 4, 5]]
console.log(copy); // [1, 2, [3, 4, 5]]
このように、ネストした配列やオブジェクトがある場合は注意が必要です。
5. ポイント整理
スプレッド構文とsliceメソッドは、JavaScriptで配列をコピーする基本的な方法です。元の配列を変えずに新しい配列を作りたいときに役立ちます。ただし、配列の中に配列やオブジェクトがある場合は「浅いコピー」なので中身まではコピーされないことを理解しておきましょう。
まとめ
JavaScriptで配列をコピーする方法として学んだスプレッド構文とsliceメソッドは、さまざまな場面で使える非常に便利な知識です。配列の内容をそのまま保ちながら新しい配列を作る操作は、日常的なコードの中でもよく登場し、データの加工や状態管理を行うときに欠かせない基本となります。今回の記事では、それぞれの仕組みがどう働くのか、具体的な例を通して分かりやすく確認してきました。 まず、スプレッド構文は配列の中身をひとつずつ広げて新しい配列を作る方法で、見た目も直感的で分かりやすいという特徴があります。りんごやみかんのような果物の配列を使った例では、元の配列を変えずにコピーできることや、同じ値を持つ別の配列として扱える仕組みがよく理解できました。また、イコール記号で配列を代入しただけでは同じ配列を共有してしまい、コピーにならないこともより深く把握できたはずです。 一方、sliceメソッドはもともと配列の一部を切り出すためのメソッドですが、引数を何も指定しないことで全体をコピーできるという特徴があります。スプレッド構文と同じように、新しい配列を作りつつ元の配列には影響を与えないため、用途に応じてどちらを使っても同じように扱えます。特に、配列操作を学び始めたばかりの人にとっては、sliceメソッドのほうが「切り出す」という動作と結び付きやすく、理解しやすいというメリットもあります。 さらに、コピーした配列が元の配列とは別の「箱」であるという点も重要です。コピーした配列に新しい要素を追加しても、元の配列にはまったく影響がありません。この性質により、アプリケーションの状態管理やデータ編集を安全に行うことができ、意図せず元のデータを変更してしまうミスを避けることができます。 そして、最後に理解しておきたいのが「浅いコピー」という概念です。スプレッド構文もsliceメソッドも浅いコピーであるため、配列の中に配列やオブジェクトが入っていると、その内側まではコピーされません。つまり、それらは元の配列とコピーした配列の両方から共有される状態になります。この特性は最初は少し難しく感じますが、実際のプログラムを書く中で繰り返し触れることで理解が深まります。 以下に今回の内容を総合的に確認できるサンプルコードをまとめています。スプレッド構文、sliceメソッド、浅いコピーの動きなど、記事で学んだ要素をぎゅっと詰め込んだ内容なので、もう一度じっくり見直してみてください。
サンプルプログラムまとめ
// スプレッド構文でコピー
let fruits = ["りんご", "みかん", "バナナ"];
let copyA = [...fruits];
console.log(copyA);
// sliceでコピー
let copyB = fruits.slice();
console.log(copyB);
// コピー後の独立性
copyA.push("ぶどう");
console.log(fruits); // ["りんご", "みかん", "バナナ"]
console.log(copyA); // ["りんご", "みかん", "バナナ", "ぶどう"]
// 浅いコピーの例
let nested = [1, 2, ["さくら", "あお"]];
let nestedCopy = [...nested];
nestedCopy[2].push("みどり");
console.log(nested);
console.log(nestedCopy);
生徒
「今日の内容で、配列をコピーする方法がしっかり分かりました。スプレッド構文もsliceメソッドも、実際に使ってみるととても分かりやすいですね。」
先生
「そうですね。どちらも覚えておくと本当に便利ですよ。特に、元の配列をそのまま保ちたいときには必須といっていいほどです。」
生徒
「コピーした配列なら、変更しても元の配列に影響しないというところが、とても分かりやすかったです。実際にコードで確認できたのがよかったです。」
先生
「それに加えて、浅いコピーの性質も大事なポイントです。同じ配列の中に別の配列がある場合、内側まではコピーされないという点は特に覚えておきましょう。」
生徒
「浅いコピーは最初こそ難しく感じましたが、例を見たら納得できました。今後の配列操作にも役立ちそうです。」
先生
「その調子です。実際に手を動かしてコードを書くことで、理解はさらに深まりますよ。」