JavaScriptでは、ES6からspreadオペレーターとrestパラメーターという構文が使えるようになりました。

どちらとも「…」の省略記号が用いられ、配列やオブジェクトに良く使われています。
一見似たような機能があると思われそうですが、使用できる場所や要素の扱い方が異なることから、実際には反対の働きを持っていることが特徴です。

そこで今回は、spreadオペレーター・restパラメーターは何か、またその違いについて解説していきます。

spreadオペレーター

「spreadオペレーター」とは、繰り返し可能なオブジェクト(配列・オブジェクト・文字列など)を任意の箇所で展開するための構文です。
関数の引数や、配列やオブジェクトの複製などに使われています。

spreadオペレーターは、以下のように「…」を用いて使用します。

...繰り返し可能なオブジェクト

ここからは、どのような場面でspreadオペレーターを活用できるか見ていきましょう。

配列に利用

以下は、もっとも基本的な例で、文字列を配列で展開しています。

let string = 'defg';

let array = ['a', 'b', 'c', ...string];

console.log(array);
//["a", "b", "c", "d", "e", "f", "g"]

配列の中で「…変数」と記述すると、spreadオペレーターを使用した箇所に、オブジェクト(この場合は文字列)が展開されることが分かります。

配列のマージに利用

以下は、複数の配列要素を一つの配列として結合する例です。

const colorsA = ['black', 'white'];
const colorsB = ['blue', 'purple'];

const colorsC = [...colorsA, ...colorsB, 'yellow', 'orange'];
console.log(colorsC);
//["black", "white", "blue", "purple", "yellow", "orange"]

「…変数1, …変数2」のように、複数のspreadオペレーターを使用することで、いくつかの要素をまとめることもできます。

関数の引数に利用

以下は、関数の引数として配列要素をとる例です。

let score = [80, 63, 100];

const averageScore = (x, y, z) => {
  return (x + y + z) / 3;
};

console.log(averageScore(...score));
//81

「関数(…変数)」と記述するだけで、配列要素が引数に展開されます。

オブジェクトの複製に利用

オブジェクトを複製する場合には、「Object.assign」という方法がありますが、spreadオペレーターを使うと便利です。

const animals = {
  animalA: 'panda',
  animalB: 'rabbit',
  animalC: 'tiger'
};

const copy1 = Object.assign({}, animals);
const copy2 = { ...animals };

console.log(copy1); //{animalA: "panda", animalB: "rabbit", animalC: "tiger"}
console.log(copy2); //{animalA: "panda", animalB: "rabbit", animalC: "tiger"}

結果は同じですが、spreadオペレーターを使うcopy2の方が、直感的で記述も楽です。

あくまで複製のため、コピー元の「animals」とは別のものだと判断されます。

console.log(animals === copy1); //false
console.log(animals === copy2); //false
console.log(copy1 === copy2); //false

配列の複製に利用

配列の複製には、「Array.slice」が使われることがありますが、ここでもspreadオペレーターが役に立ちます。
オブジェクトの複製と同様の方法です。

const animals = ['panda', 'rabbit', 'tiger'];

const copy1 = animals.slice();
const copy2 = [...animals];

console.log(copy1); //["panda", "rabbit", "tiger"]
console.log(copy2); //["panda", "rabbit", "tiger"]

console.log(animals === copy1); //false
console.log(animals === copy2); //false
console.log(copy1 === copy2); //false

こちらも、spreadオペレーターを使うcopy2の方がすっきりして見えます。
また、コピー元の配列とコピーした配列は、別のものと認識されることが確認できます。

restパラメーター

「restパラメーター」とは、複数の要素を1つのオブジェクトとして集約するための構文です。
「rest」と呼ばれるだけあり、残りのものを集めるという役割があります。

restパラメーターは、以下のように「…」を用いて使用します。
複数の要素を関数の引数に用意することが可能です。

function(引数1, 引数2, ...残り) {}

また、restパラメーター以前の引数には数の制限がありませんが、restパラメーター自体は引数の最後にしか置くことができないため、注意が必要です。
そのため、以下はエラーとなります。

function(引数1, ...残り, 引数2) {}

サンプル

では、実際にrestパラメーターを使ってみます。
以下は、プロフィール情報を関数の引数に入れた例です。

const myInfo = (myName, ...detail) => {
  console.log(myName);
  console.log(detail);
};

myInfo('Emma', 'from UK', 'Web developer');
//"Emma"
//["from UK", "Web developer"]

rest parameter1

関数の引数に「myName」と、それ以外は「…detail」にまとめて文字列を渡しています。
その結果、「myInfo()」の1つ目の文字列がmyNameに代入され、残りはdetailとして渡ります。

また、detailに渡った残りの要素は、自動的に配列として変換されるため、配列への変換が必要な場合には、その作業が必要なくなります。

restパラメーターは、「{ name: value}」のように、オブジェクト形式で使用することもできます。

const myInfo = ({name: myName, ...detail}) => {
  console.log(myName);
  console.log(detail);
};

myInfo({name: 'Emma', from: 'UK', job: 'Web developer'});
//"Emma"
//{from: "UK", job: "Web developer"}

rest parameter2

この場合、残りの要素はオブジェクト形式で出力されることが分かります。

引数の数が決まっていない場合に、restオペレーターを使用して繰り返し処理を行うと便利です。

まとめ

今回は、spreadオペレーターとrestパラメーターについて解説しました。

どちらも「…」を扱う構文ですが、機能と使う場所が異なることが分かりました。

・spreadオペレーター
-複数の要素を一つずつ展開する
-関数を呼び出すときに使用

・restパラメーター
-複数の要素を一つにまとめる
-関数を宣言するときに使用

オブジェクトや配列の操作には色々な方法がありますが、それらを理解した上でspreadオペレーターやrestパラメーターを使えるようになると、従来の書き方よりも楽に要素の展開や集約ができるようになります。

ぜひ参考にして取り入れてみてください。

JavaScript関連記事