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"]

関数の引数に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オペレーターを使用して繰り返し処理を行うと便利です。

まとめ

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

どちらもを扱う構文ですが、機能と使う場所が異なることが確認できました。

// spreadオペレーター
* 複数の要素を一つずつ展開する
* 関数を呼び出すときに使用する
// restパラメーター
* 複数の要素を一つにまとめる
* 関数を宣言するときに使用する

spreadオペレーターやrestパラメーターを使えるようになると、オブジェクトや配列、関数を便利に操作できるようになります。
ぜひ参考にして取り入れてみてください。

spreadオペレーター・restパラメーターの関連記事

関数オブジェクト
argumentsオブジェクト