スプレッド構文を制するものは反復可能オブジェクトを制する

#はじめに
ES2015から使えるようになり、徐々にコード内でも市民権を得てきた **スプレッド構文** 。
とても便利な構文なので備忘録もかねてまとめてみました。

#スプレッド構文とは
よく見るピリオド3つのコイツです。

`...`

組織によっては可読性等の問題から使用を控えるように教えられているところもあるかもしれません。
初めて見る方もいると思うので、リファレンスから説明を引用します。

>スプレッド構文を使うと、配列式や文字列などの反復可能オブジェクトを、 0 個以上の引数 (関数呼び出しの場合) や要素 (配列リテラルの場合) を期待された場所で展開したり、オブジェクト式を、 0 個以上のキーと値のペア (オブジェクトリテラルの場合) を期待された場所で展開したりすることができます。

###反復可能なオブジェクトとは
iterablesなオブジェクトとも言われます。
簡単にいうと `for..of` ループで動作できるものになります。

一番イメージがつきやすいのは配列ではないでしょうか。

###配列を展開？
簡単にいうと配列から中身を全部出してくれるという様なイメージです。
以下のサンプルコードでは、スプレッド構文を使う事で配列を **展開** して `sum関数` の引数にセットしてくれます。

```sample.js
function sum(x, y, z) {
  return x + y + z;
}

const numbers = [1, 2, 3];

console.log(sum(...numbers)); // 6
```

###使いこなすととても便利
組織のローカルルールやサービスの対象とするブラウザによっては使えない構文ではありますが、使いこなすととても便利なので是非、チートシートとして読んでみてください。

#配列の複製
既存の配列から新たに配列を作成します。

```sample.js
const sampleArr = [{ 'key1': 100 }, { 'key2': 200 }];

const copyArr = [...sampleArr]; // スプレッド構文でコピー
console.log(copyArr); // [{ key1: 100 }, { key2: 200 }]

```

このように `Array.from()` などを使わないスマートなコードになります。

###ただしシャローコピーなので注意
スプレッド構文や `Array.from()` などではコピー元の配列と参照元は同じになるので、しっかりと意識しておきましょう。
ディープコピーがしたい場合は `JSON.stringify()` で文字列変換してから再び `JSON.perse()` で配列に戻すなどの対処が必要です。

```sample.js
const sampleArr = [{ 'key1': 100 }, { 'key2': 200 }];

const copyArr = [...sampleArr]; // スプレッド構文でコピー

copyArr['0'].key1 = 'changed'; // key1を'changed'に変更
console.log(copyArr['0'].key1);  // changed
```

#配列の先頭に要素を追加
もちろん配列の先頭に既存の配列を追加することも可能です。

```sample.js
const sampleArr1 = [1, 2, 3];
const sampleArr2 = ['d', 'e', 'f'];

sampleArr1.unshift(...sampleArr2);
console.log(sampleArr1);    // ['a', 'b', 'c', 1, 2, 3]
```

#配列の末尾に要素を追加
配列の末尾に既存の配列を追加したい時もスプレッド構文の出番です。

```sample.js
const sampleArr1 = [1, 2, 3];
const sampleArr2 = ['d', 'e', 'f'];

sampleArr1.push(...sampleArr2); // スプレッド構文で末尾に追加
console.log(sampleArr1);    // [1, 2, 3, 'a', 'b', 'c']
```

#複数の配列を合成
複数の配列をひとつにまとめることも可能です。

```sample.js
const sampleArr1 = [1, 2, 3];
const sampleArr2 = ['d', 'e', 'f'];

const mergeArr = [...sampleArr1, ...sampleArr2];
console.log(mergeArr); // [ 1, 2, 3, 'd', 'e', 'f' ]
```

#配列から重複する要素を取り除く
スプレッド構文HACKの中でも一番便利な使い方だと思ってます。

重複を許容しない `Setオブジェクト` を使うことで配列から重複を取り除き、スプレッド構文と組み合わせることで、配列に戻してあげることができます。

```sample.js
const sampleArr = ['a', 'b', 'b', 'c', 'd', 'd'];
const removedArr = [...(new Set(sampleArr))];

console.log(removedArr);    // [ 'a', 'b', 'c', 'd' ]
```

#文字列を配列に変換
今までは `.split('')` などを用いていた処理もこんなに簡単にかけてしまいます。

```sample.js
const string = 'Hello World';
const convertedArr = [...string];

console.log(convertedArr); //  [ 'H', 'e', 'l', 'l', 'o', ' ', 'W', 'o', 'r', 'l', 'd' ]
```

##オブジェクトの複製
スプレッド構文の出番は配列だけではありません。
反復可能であれば何でも使えてしまいます。

配列と同様にオブジェクトの複製も、こんなにスマートに書けるんです。

```sample.js
const sampleObj = {key1: 1, key2: 2, key3: 3, };

const copyObj = {...sampleObj};
console.log(copyObj); // { key1: 1, key2: 2, key3: 3 }
```

###ただしシャローコピーなので注意
配列編と同じように、これもまたシャローコピーなので使用方法には注意してください。
ディープコピーがしたい場合は `JSON.stringify()` で文字列変換してから再び `JSON.perse()` でオブジェクトに戻すなどの対処が必要です。

##オブジェクトの合成
配列と同様にオブジェクトも簡単に合成することができます。

```sample.js
const sampleObj1 = {key1: 1, key2: 2, key3: 3, };
const sampleObj2 = {key4: 4, key5: 5, key6: 6, };

const copyObj = {...sampleObj1, ...sampleObj2};
console.log(copyObj); // { key1: 1, key2: 2, key3: 3, key4: 4, key5: 5, key6: 6 }
```

#まとめ
スプレッド構文はまだまだ新しい構文なので、組織やブラウザによっては禁止されているところもあるかもしれませんが、上手に使い分けることでスマートなコーディングが可能になるのではないでしょうか。