はじめに
こんにちは。
JavaScriptのコードで ... という記号を見かけることがあります。
これはスプレッド構文と呼ばれる、配列やオブジェクトの中身を展開するための書き方です。
この記事では、配列とオブジェクトそれぞれでのスプレット構文の使い方を整理します。
スプレッド構文とは
スプレッド構文は、配列やオブジェクトなどを展開するための構文です。
MDNでは次のように説明されています。
スプレッド構文 (
...) 構文を使うと、配列式や文字列などの反復可能オブジェクトを、0 個以上の引数(関数呼び出しの場合)や要素(配列リテラルの場合)を目的の場所に展開することができます。
配列での使い方
配列を展開する
配列リテラルの中で ... を使うと、配列の要素がその場に展開されます。
const colors = ["red", "yellow"];
const newColors = ["blue", ...colors, "green"];
console.log(newColors); // [ 'blue', 'red', 'yellow', 'green' ]
...colors の部分に "red" と "yellow" が展開されています。
配列をコピーする
const colors = ["red", "yellow"];
const copiedColors = [...colors];
console.log(copiedColors); // [ 'red', 'yellow' ]
[...colors] は、colors の要素を展開して新しい配列に入れ直しています。
ただし、これはシャローコピーです。
配列の中にオブジェクトが入っている場合、オブジェクト自体は同じものを参照します。
const users = [{ name: "Alice" }];
const copiedUsers = [...users];
copiedUsers[0].name = "Bob";
console.log(users[0].name); // "Bob"
コピーの中身を書き換えたのに、元の配列の中身まで変わってしまっています。外側の配列は別物ですが、中のオブジェクトは共有されたままなのです。
ディープコピーを行いたい場合は structuredClone() などを使う必要があります。
シャローコピーとは、オブジェクトや配列の一番外側だけをコピーすることです。ネストした値は、コピー元とコピー先で同じものを参照します。
反対に、ネストした値も含めてすべてを独立した別物としてコピーすることをディープコピーと呼びます。
配列を結合する
複数の配列を1つにまとめることもできます。
const warmColors = ["red", "orange"];
const coolColors = ["blue", "green"];
const colors = [...warmColors, ...coolColors];
console.log(colors); // [ 'red', 'orange', 'blue', 'green' ]
concat() でも同じことはできますが、スプレッド構文なら途中に要素を追加するのも自然に書けます。
const colors = [...warmColors, "yellow", ...coolColors];
関数の引数に展開する
配列の要素を、関数の引数として渡すこともできます。
function add(a, b, c) {
return a + b + c;
}
const numbers = [1, 2, 3];
console.log(add(...numbers)); // 6
オブジェクトでの使い方
オブジェクトをコピーする
オブジェクトリテラルの中で ... を使うと、プロパティが展開されます。
const user = {
id: 1,
name: "Alice",
};
const copiedUser = { ...user };
console.log(copiedUser); // { id: 1, name: 'Alice' }
配列のときと同様に、これもシャローコピーです。
オブジェクトをマージする
複数のオブジェクトのプロパティを1つにまとめることができます。
const user = {
id: 1,
name: "Alice",
};
const profile = {
age: 20,
city: "Tokyo",
};
const mergedUser = { ...user, ...profile };
console.log(mergedUser); // { id: 1, name: 'Alice', age: 20, city: 'Tokyo' }
同じプロパティは後ろが勝つ
展開時に同じプロパティ名がある場合、後に書いた方の値が使われます。
const user = {
id: 1,
name: "Alice",
};
const updatedUser = {
...user,
name: "Bob",
};
console.log(updatedUser); // { id: 1, name: 'Bob' }
...user で name: "Alice" が展開されたあとに name: "Bob" が来るため、最終的に "Bob" で上書きされます。
まとめ
- スプレッド構文は、配列やオブジェクトの中身を展開する構文
- 配列では、コピー・結合・関数への引数展開に使える
- オブジェクトでは、コピー・マージ・一部プロパティの上書きに使える
- コピーはシャローコピーであり、ネストした値は共有される
お読みいただきありがとうございました。