Javascriptで利用できる便利なスプレッド構文(…)の使い方について紹介していきます。
本記事で学べる事
- スプレッド構文を使用した配列の出力
- 分割代入を使用したスプレッド構文
- スプレッド構文で配列をまとめる方法
- 配列をスプレッド構文でコピーと結合
スプレッド構文とは
Javascriptのコードを読んでいるとたびたび下記ようにピリオドを3つ連続で記述された構文を見たことはありますでしょうか。
これはスプレッド構文と呼ばれる記述方法です。
console.log(...dogs);
スプレッド構文について公式のリファレンスなどでは以下のように定義されています。
スプレッド構文 (
https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Operators/Spread_syntax...
) を使うと、配列式や文字列などの反復可能オブジェクトを、0 個以上の引数 (関数呼び出しの場合) や要素 (配列リテラルの場合) を期待された場所で展開したり、オブジェクト式を、0 個以上のキーと値の組 (オブジェクトリテラルの場合) を期待された場所で展開したりすることができます。
私はあまり賢い方ではないので上記の説明ではさっぱり理解できませんでした。
簡単に説明をするとスプレッド構文とは配列やオブジェクトの中身を展開する記述方法になります。
スプレッド(spread)とは『拡げる、展開する』という意味の英単語で、スプレッド構文を使用することで冗長な記述をシンプルに書けるようにでき可読性が向上します。
言葉だけではなかなか理解しづらい内容となりますのでサンプル構文を利用して解説をさせていただきます。
また、今回の記事では分割代入を利用した説明も行っているため、『分割代入って何?』という方は別記事で詳細に解説をしているためそちらを参照してください。
【JavaScript】オブジェクトや配列の操作が楽になる分割代入の使い方
スプレッド構文で配列の値を出力する
配列で使用されるスプレッド構文の使い方について紹介していきます。
スプレッド構文では配列の値を簡単に出力させることができます。
まず、配列dogsを定義して2つの要素(シーズーとダックス)を作成します。
const dogs = ["シーズー", "ダックス"]; console.log(dogs); 出力結果:(2) ["シーズー", "ダックス"]
作成した配列から値を取得して処理結果を返すmsg関数を定義します。
const msg = (dog1, dog2) => { return dog1 + "と" + dog2 + "、二人は仲良し"; };
では、実際に定義した関数msgに配列dogsの値を渡して処理を実行してみましょう。
今回は通常の配列の処理とスプレッド構文を利用した処理の2パターンのサンプル構文を作成しました。
サンプル構文(通常の配列)
const dogs = ["シーズー", "ダックス"]; const msg = (dog1, dog2) => { return dog1 + "と" + dog2 + "、二人は仲良し"; }; console.log(msg(dogs[0], dogs[1]); 出力結果:シーズーとダックス、二人は仲良し
サンプル構文(スプレッド構文)
const dogs = ["シーズー", "ダックス"]; const msg = (dog1, dog2) => { return dog1 + "と" + dog2 + "、二人は仲良し"; }; console.log(msg(...dogs); 出力結果:シーズーとダックス、二人は仲良し
2つのサンプル構文で異なる記述をしているのはmsg関数を呼び出している部分だけとなります。
異なる部分を並べて比較していきましょう
//通常の配列の展開 console.log(msg(dogs[0], dogs[1]); //スプレッド構文による配列の展開 console.log(msg(...dogs);
見ていただければわかる通り、スプレッド構文を使用した方が記述内容が少なくなっており、とても見やすいですね。
通常の配列では要素を一つ一つ関数msgに渡す必要がありますが、スプレッド構文(…)のピリオド3つを配列名の前につけるとすべての要素を関数に繰り返し渡しているという処理になります。
そのため要素ごとに記述する必要がなく、シンプルな構文となっています。
スプレッド構文で配列の操作を行う
スプレッド構文は配列を展開するだけではなくほかにも下記のような複数の用途があります。
- 配列の要素を一部まとめる(抜き出す)
- 配列のコピー
- 配列の結合
配列の要素を一部まとめる(分割代入)
配列の要素を一部まとめて新たな配列として扱う方法について紹介していきます。
const dogs = ["シーズー", "ダックスフンド", "柴犬"];
上記のように複数の犬種を格納した配列dogsを定義します。
この配列の最初の要素であるシーズーを分割代入で取り出し、残りのダックスフンド、柴犬はスプレッド構文を利用して新たな配列としてまとめたいと思います。
サンプル構文
//配列dogsを定義 const dogs = ["シーズー", "ダックスフンド", "柴犬"]; //変数dogにはシーズーを格納。残りの要素をdogs2としてまとめる const [dog, ...dogs2] = dogs; //変数dogと新たに定義した配列dogs2を出力 console.log(dog); console.log(dogs2); //出力結果 シーズー (2) ["ダックスフンド", "柴犬"]
配列dogsはそれぞれ以下のように分割されています
- 変数dog = “シーズー”
- dogs2 = [“ダックスフンド”, “柴犬”]
一番最初の要素であるシーズーが変数dogに分割代入されて、残りの要素であるダックスフンドと柴犬は新たな配列dogs2として定義してあります。
この新たな配列として定義してある部分をスプレッド構文を利用して一括で格納されていることがわかります。
実際に出力結果を確認するとそれぞれ与えられた変数dogと配列dogs2に正しく値が分配されて想定通りの出力を確認することができました。
スプレッド構文ではこのように既に定義されている配列の要素の一部を新たな配列として定義して利用することができます。
スプレッド構文で配列をコピーする
スプレッド構文を利用して既に定義されている配列をコピーして出力する方法と注意点について紹介していきます。
先ほどと同様の下記の配列を利用していきます。
const dogs = ["シーズー", "ダックスフンド", "柴犬"];
この配列をスプレッド構文を利用してコピー&出力を行います
サンプル構文
//配列dogsを定義 const dogs = ["シーズー", "ダックスフンド", "柴犬"]; //新たに配列dogs2を定義する。その要素として配列dogsをコピーする const dogs2 = [...dogs]; //要素の出力 console.log(dogs); console.log(dogs2); //出力結果 (3) ["シーズー", "ダックスフンド", "柴犬"] (3) ["シーズー", "ダックスフンド", "柴犬"]
サンプル構文では既存の配列dogsを新たに定義した配列dogs2にコピーしています。
スプレッド構文は配列の全ての要素を展開する記述ですので、配列dogを大括弧[]で囲い、配列名の前に…を記述します。
これによりすべての要素を取り出して配列dogs2に格納することができます。
出力結果はどちらも同様の値が出力されているのが確認できます。
スプレッド構文で配列をコピーする理由
上記にてスプレッド構文で配列をコピーする方法について紹介していましたが、下記のような記述でも同じ配列であれば作成することができます
//配列dogsを定義 const dogs = ["シーズー", "ダックスフンド", "柴犬"]; //新たに配列dogs2を定義する。既に定義されている配列dogsを指定する const dogs2 = dogs; //要素の出力 console.log(dogs); console.log(dogs2); //出力結果 (3) ["シーズー", "ダックスフンド", "柴犬"] (3) ["シーズー", "ダックスフンド", "柴犬"]
上記サンプル構文のようにスプレッド構文で記述しなくても同じ配列自体は作成することができますが、こちらには重大な欠点があります。
もし配列dog2の最初の要素のみ”パグ”に書き換えたい場合に上記のような記述をしてしまうと出力がどのように変化するか見てみましょう。
//配列dogsを定義 const dogs = ["シーズー", "ダックスフンド", "柴犬"]; //新たに配列dogs2を定義する。既に定義されている配列dogsを指定する const dogs2 = dogs; dogs2[0] = "パグ"; //要素の出力 console.log(dogs); console.log(dogs2); //出力結果 (3) ["パグ", "ダックスフンド", "柴犬"] (3) ["パグ", "ダックスフンド", "柴犬"]
いかがでしょうか。要素を変更したのは新しく定義した配列dog2の最初の要素であるにもかかわらず、コピー元の配列dogsの要素も変化してしまっていることがわかります。
この原因は配列の代入は要素を渡しているのではなく、既に作成された配列の参照を引き継いでいるということにあります。
配列dogsと配列dogs2は名前を変えただけで実際には同一の配列を指しているということです。
そのため、今回のサンプル構文のような想定していない不具合が生じてしまいます。
ですので、配列をコピーしたい場合には参照を引き継がせるだけの配列の代入ではなく、要素自体を同じものを引き継いで、新しい配列を生成させるスプレッド構文を使用したコピー方法を利用するようにしましょう。
配列の結合
スプレッド構文を利用した配列の結合する方法について紹介していきます。こちらはすでに紹介した、配列のコピーと同じような考え方で実現することができます。
まず最初に下記のような2つの配列を定義します。
//配列dogs1とdogs2を定義 const dogs1 = ["シーズー", "ダックスフンド"]; const dogs2 = ["パグ","柴犬"];
定義した2つの配列をスプレッド構文を利用して1つにまとめて新しい配列dogs3を作成します。
サンプル構文
//配列dogs1とdogs2を定義 const dogs1 = ["シーズー", "ダックスフンド"]; const dogs2 = ["パグ", "柴犬"]; //新しく配列dogs3を定義して値を代入 const dogs3 = [...dogs1, ...dogs2]; //要素の出力 console.log(dogs3); //出力結果 (4) ["シーズー", "ダックスフンド", "パグ", "柴犬"]
2つの配列を1つにまとめて新しい配列dogs3を作成することができました。