JavaScriptのスプレッド構文を完全解説！【初心者向け】

JavaScriptのスプレッド構文（Spread Syntax）は、日常的なプログラミングを効率化する強力なツールです。**...の3つのドット** で表現され、配列やオブジェクトを簡単に展開したりコピーしたりできます。本記事では、スプレッド構文の使い方から実践的な例まで解説します。

# スプレッド構文とは？

スプレッド構文は、配列やオブジェクトの要素を **展開** するための構文です。
以下のような場面で活用されます。
- 配列やオブジェクトのコピー
- 配列やオブジェクトの結合
- 関数の引数として要素を渡す

基本構文は以下のとおりです。

```javascript
const array = [1, 2, 3];
const newArray = [...array]; // [1, 2, 3]
```

# 配列におけるスプレッド構文

### 1 配列のコピー

スプレッド構文を使うと、簡単に配列をコピーできます。

```javascript
const original = [1, 2, 3];
const copy = [...original];
console.log(copy); // [1, 2, 3]
```

注意: スプレッド構文は「浅いコピー」を作成します。ネストされたオブジェクトや配列には注意が必要です。

### 2 配列の結合

複数の配列を結合する場合にも便利です。

```javascript
const array1 = [1, 2];
const array2 = [3, 4];
const combined = [...array1, ...array2];
console.log(combined); // [1, 2, 3, 4]
```

### 3 新しい要素の追加

スプレッド構文を使って、新しい要素を簡単に追加できます。

```javascript
const original = [2, 3];
const updated = [1, ...original, 4];
console.log(updated); // [1, 2, 3, 4]
```

# オブジェクトにおけるスプレッド構文

スプレッド構文はオブジェクトにも使えます。

### 1 オブジェクトのコピー
```javascript
const obj = { a: 1, b: 2 };
const copy = { ...obj };
console.log(copy); // { a: 1, b: 2 }
```

### 2 プロパティの追加・上書き

既存のオブジェクトにプロパティを追加・上書きできます。
```javascript
const original = { a: 1, b: 2 };
const updated = { ...original, b: 3, c: 4 };
console.log(updated); // { a: 1, b: 3, c: 4 }
```

### 3 オブジェクトの結合

複数のオブジェクトを結合できます。
```javascript
const obj1 = { a: 1 };
const obj2 = { b: 2 };
const merged = { ...obj1, ...obj2 };
console.log(merged); // { a: 1, b: 2 }
```

# スプレッド構文の活用例

### 1 関数への引数展開

スプレッド構文は、配列の要素を関数の引数として展開するのに便利です。

```javascript
function sum(x, y, z) {
  return x + y + z;
}

const numbers = [1, 2, 3];
console.log(sum(...numbers)); // 6
```

### 2 初期値付きのオブジェクト作成

デフォルトの値を持つオブジェクトを作成する際に活用できます。

```javascript
const defaultSettings = { theme: "light", showNotifications: true };
const userSettings = { showNotifications: false };
const finalSettings = { ...defaultSettings, ...userSettings };

console.log(finalSettings); // { theme: "light", showNotifications: false }
```
# 注意点
### 1 浅いコピーであること

**浅いコピーとは？**
スプレッド構文で作成されるコピーは「浅いコピー（shallow copy）」です。これは、 **配列やオブジェクトの一番外側だけをコピーする** という意味です。
- 外側の値がプリミティブ型（数字や文字列など）の場合 → 問題なし
- 外側の値がオブジェクトや配列の場合 → 内部の参照先はコピーされない（元のデータとリンクされる）

例で説明
```javascript
// 配列の浅いコピー
const nestedArray = [[1, 2], [3, 4]];
const shallowCopy = [...nestedArray];

// コピーの一部を変更
shallowCopy[0][0] = 99;

// 元の配列も影響を受ける
console.log(nestedArray[0][0]); // 99
```

shallowCopyを変更したのに、元のnestedArrayまで変更されてしまいました。これは「内部の配列の参照先」がそのままコピーされたからです。

**解決方法：深いコピー（Deep Copy）**

深いコピーは、配列やオブジェクトのすべての階層をコピーします。スプレッド構文では深いコピーはできないため、別の方法を使う必要があります。

**解決例**

structuredCloneを用いる
```javascript
const nestedArray = [[1, 2], [3, 4]];
const deepCopy = structuredClone(nestedArray);

deepCopy[0][0] = 99;
console.log(nestedArray[0][0]); // 1 （元の配列は変更されない）
```

### 2 イテラブル（繰り返し可能なもの）しか展開できない

スプレッド構文は、イテラブル（iterable）なデータ型でのみ使えます。

**イテラブルとは？**

イテラブルは、ループ可能なデータ型のことです。例えば以下のようなデータ型があります。
- 配列 []
- 文字列 "abc"
- Set [1, 2, 3]
- Map {key: value}

オブジェクトはイテラブルではないため、そのままスプレッド構文を使うとエラーになります。

**例**
```javascript
const obj = { a: 1, b: 2 };

// イテラブルではないのでエラー
// console.log(...obj); // エラー: オブジェクトは展開できません
```
**解決方法**

オブジェクトを展開したい場合は、スプレッド構文を **{ ...obj } の形** で使います。
```javascript
const obj = { a: 1, b: 2 };
const newObj = { ...obj };
console.log(newObj); // { a: 1, b: 2 }
```
### 3 プロパティの上書き順序

オブジェクトをマージするとき、後から書かれたプロパティが優先されます。

例
```javascript
const defaults = { theme: "light", showNotifications: true };
const userSettings = { theme: "dark" };

const finalSettings = { ...defaults, ...userSettings };
`onsole.log(finalSettings); // { theme: "dark", showNotifications: true }
```
themeがdefaultsの"light"からuserSettingsの"dark"に上書きされています。

# まとめ

スプレッド構文は、JavaScriptでのデータ操作を簡単かつ効率的にする便利なツールです。配列やオブジェクトの操作に慣れてきたら、ぜひスプレッド構文を活用してコードの可読性と効率を向上させてみてください！

この記事がスプレッド構文の理解に役立てば幸いです。質問や追加の例があれば、コメントでぜひ教えてください！