今すぐ使いたいスプレッド構文、"Three-dots" Tip 集

<img width="822" alt="Screen Shot 2020-06-17 at 6.40.18 PM.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/663749/01503c24-fb74-966e-d940-49055d5b23cc.png">

こんにちは。また転職しますので、以前仕事で使っていたアカウントから切り離して新しいアカウントからこれを書いています。（なので現在フォロワー０からの再出発！）

この記事は１０日ほど前に私が [Dev.to](https://dev.to/girlie_mac/spread-syntax-three-dots-tricks-you-can-use-now-aob) で投稿したものと同じ内容なのですが、Must-read に選ばれるほどの好評でしたので日本語でも書いてみることにしました。

---

ES6 (ECMAScript 2015, the 6th edition) が標準化されて５年経ちました。この通称 ES6 は多くの新機能や、シンタックティカル・シュガーが追加され、簡潔で明瞭な構文で記述できるようになりました。

たとえば `class` 構文、`let` / `const`、アロー関数などは、みなさんもすでに普段から使っていると思います。では、通称 "three-dots" とも呼ばれる [**Spread operator** / スプレッド構文](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_syntax)はどうでしょうか。あまり積極的に使っていない方が多いのではないでしょうか。 

私は個人的はとても便利だと感じていますので、コードを書いてて見つけた便利な使い方を紹介してみようと思います。もちろん普段はコードを書くのに StackOverflow 参考にすることも多いことは隠すつもりはないので、そうして誰かがシェアしたものの中で便利だと思ったコードは自分で普段使ってクセにしていって、そのうち自分でもいろいろ見つけた、というのが本当のところです。


## Three Dots って？

ES6 で追加された "three-dots" シュガー には、可変長引数を配列で受け取る [**Rest parameter** / 残余引数](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Functions/rest_parameters)と、シンタックスが似ていますが、逆に配列を展開する**スプレッド構文**があります。

この記事ではスプレッド構文の方の紹介をしていきます。この定義の説明を読んで理解するよりも、これから紹介する実際の使えるコードをみてもらった方がわかりやすいと思います。

🔴 🟠 🟡 

### Concat （配列の結合）

"Con**cat**" ということで猫の毛色を含む２つの配列があります。🐱

```js
const arr1 = ['solid', 'bicolor', 'tabby'];
const arr2 = ['calico', 'tortoiseshell'];
```

ES6 以前では、元来の方法で `concat()` を使ってこう書いてきました:

```js
var conCats = arr1.concat(arr2);
// ['solid', 'bicolor', 'tabby', 'calico', 'tortoiseshell']
```

ES6 スプレッド構文ではこう書くことができます:

```js
const conCats = [...arr1, ...arr2]; 
// ['solid', 'bicolor', 'tabby', 'calico', 'tortoiseshell']
```

### 文字列 → 配列 変換 

文字を反転にせよ、もしくは、回文を作れというような問題はソフトウェア・エンジニアの面接のあるあるなのではないでしょうか。実際の問題はもっと複雑なものかもしれませんが、似たような問題で、問題を解決するには、まず文字列を配列に変換する、というようなものが結構多いかと思います。


まず文字列があります:

```js
const str = 'kitty';
```

ES6 以前では `split()` を使って一文字づつ配列におさめることができました:

```js
var newArr = str.split(''); // ['k', 'i', 't', 't', 'y'];
```

ES6 スプレッド構文を使えばもっと楽に:

```js
const newArr = [...str]; // ['k', 'i', 't', 't', 'y'];
```

### Max または Min の値

まず、このような値が与えられたとします。

```js
10, 9, 6, 12 
```
この中から最大値（または最小値）を見つけるのは `Math.max()` (or `Math.min()`) を使い、上の数値を引数としてあたえます: 

```js
var max = Math.max(10, 9, 6, 12);
```

ES6 スプレッド構文を使うとこう書くことができます: 

```js
const nums = [10, 9, 6, 12];
const max = Math.max(...nums); // 12
```

### 配列のコピー

スプレッド構文と使って配列のシャローコピーを返すことができます。

例えば、こういう配列があります。

```js
const allCatNames = ['chewie', 'leia', 'yoda', 'chewie', 'luke', 'leia'];
```

シャローコピーを得る一つの方法として、 `slice()` があります:

```js
var allCatNamesCopy = allCatNames.slice();
```

これを ES6 スプレッド構文を使うとこうなります:

```js
const allCatNamesCopy = [...allCatNames];
```

### 配列から重複を除く

上の例の配列、 `allCatNames` ではいくつかの重複 (`chewie` と `leia` が２つづつ)があります。重複を取り除いた配列を得るには ES5 では、何行もあるコードを書く必要があったかと思います。たとえば、配列をループし、それぞれの値をマッピングして同じ値があるか調べつつ新しい配列に push して最終的に重複を除いた新しい配列を返す、といったオペレーションをする必要がありました。

これを、スプレッド構文を使うと一行で書くことができます。

```js
const catNames = [...new Set(allCatNames)]; 
// ['chewie', 'leia', 'yoda', 'luke'];
```

### HTML エレメントを配列に

もしあなたが DOM 使いなフロントエンドの JavaScript ディベロッパーだったら次の例は特に便利かもしれません。

例えば、`.cat` というクラス名のついたエレメントを集めたいとします。 この時、`querySelectorAll()` で DOM ノードを収集するでしょう。

ただこの時 `document.querySelectorAll('.cat')` はノードの集合 *NodeList* であり、似てはいますが配列とは異なります。

ではこの NodeList を配列にしたい時はどうしますか？

ES5 では、このように一見わかりにくいハック的な方法をとっていたかもしれません:

```js
var catElementArray = [].slice.call(document.querySelectorAll('.cat'));
```

これを、スプレッド構文を使うとこう書くことができます:

```js
const catElementArray = [...document.querySelectorAll('.cat')];
```

---

さて、私の記事であなたが three-dots ノーテーションが気に入ったかどうかはわからないですが、今から使ってみたい、という気になった方がいましたら幸いです。

もし他に便利な使い方を見つけた方はぜひ私にもシェアしてくれると嬉しいです。

## ES.Next をもっと知りたい（さらに猫が好きな）方へ 

この夏に **ECMeowScript - What’s new in JavaScript Explained with Cats** というトークを、７月に [Forward JS](https://forwardjs.com/) (~~San Francisco~~) そして９月に [Web Directions](https://webdirections.org/) (~~Sydney~~) でする予定。コロナウイルスの影響で両方ともリモート・カンフェランスですので興味のある方が是非参加してください 🐱


では。