はじめに
いきなりですが、JavaScriptのスプレッド構文って知っていますか?
スプレッド構文とは変数名の前に…をつけるアレです。
ReactでReduxの勉強をしていたときに、急に…payloadみたいな記法が現れて、なんだこれ…??と困惑しました。
google先生に聞いてみました。「JavaScript … 構文」 🔍
すると以下の記事に目がつきました。(mozillaさん、ありがとうございます🙇♂️)

というような感じで、初めて聞いたスプレッド構文について勉強したので、まとめていこうと思います。
スプレッド構文とは…?
スプレッド構文とは、以下のような説明がされていました。
配列式や文字列などの反復可能オブジェクトを、0 個以上の引数 (関数呼び出しの場合) や要素 (配列リテラルの場合) を期待された場所で展開したり、オブジェクト式を、0 個以上のキーと値のペア (オブジェクトリテラルの場合) を期待された場所で展開したりすることができます。
https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Operators/Spread_syntax
展開と言われても正直イメージがつかないと思います。
実際にコードを書いて説明していきます。
関数の引数でスプレッド構文を使用する
1番簡単な例として、関数の引数でスプレッド構文を使用する場合を考えてみます。
function sum(x, y, z) {
return x + y + z;
}
const numbers = [1, 2, 3];
const result = sum(...numbers);
console.log(result); // 6
なんと、[1, 2, 3] → 1, 2, 3と展開され、引数に渡すことが可能になりました。
配列でスプレッド構文を使用する
次に、配列でスプレッド構文を使用する場合を考えてみます。
既存の配列を一部として使用して新しい配列を作成するには、push()やsplice()、concat()などを組み合わせる必要があります。
しかし、スプレッド構文を使用すると、すごく簡潔に記述できます。
- 既存の配列を一部として使用して新しい配列を作成
const array = ['appple', 'orange'];
const newArray = ['melon', ...array, 'banana', 'peach'];
console.log(newArray); // ['melon', 'appple', 'orange', 'banana', 'peach']
- 配列の複製を行う例
const array = ['appple', 'orange'];
const newArray = [...array];
newArray.push('banana');
console.log(array); // ['appple', 'orange']
console.log(newArray); // ['appple', 'orange', 'banana']
この時の複製はいわゆる深いコピーであり、異なる参照を持つ配列が生成されます。
そのため、newArrayに要素を追加しても、コピー元のarrayには何ら影響はありません。
- 配列の結合を行う例
let array = [0, 1, 2];
const array2 = [3, 4, 5];
array = [...array, ...array2];
console.log(array); // [0, 1, 2, 3, 4, 5]
一般的に配列の結合はconcat()を使用しますが、上記のようにスプレッド構文でも記述できます。
オブジェクトでスプレッド構文を使用する
次に、オブジェクトでスプレッド構文を使用する場合を考えてみます。
const dict = { 'name': 'nobita', 'age': 11 };
const dict2 = { 'name': 'doraemon', 'age': 20 };
const dict3 = { 'tool': 'dokodemodoor' };
const clonedObj = { ...dict };
console.log(clonedObj); // { name: 'nobita', age: 11 }
const mergedObj = { ...dict, ...dict2 };
console.log(mergedObj); // { name: 'doraemon', age: 20 }
const mergedObj2 = { ...dict, ...dict3 };
console.log(mergedObj2); // { name: 'nobita', age: 11, tool: 'dokodemodoor' }
上記の例のように、オブジェクトも配列同様に、複製やマージが可能です。
マージする際にプロパティ名が被った場合は、後に指定したオブジェクトの値で上書きされます。
React + Redux におけるスプレッド構文の使用
最後に自分が直面したReact + Reduxにおけるスプレッド構文の使用を説明します。
ReactとReduxを知らない人はすっ飛ばして大丈夫です。(ReactとReduxを知ってる方向けへの発信です)
Reducerとは、storeで管理しているstateの値を更新する役割を持ちます。
actionのtypeプロパティに応じて、stateの更新処理を定義します。
import initialState from '../store/initialState'
import * as Actions from './actions'
export const UserReducer = (state = initialState.users, action) => {
switch (action.type) {
case Actions.SIGN_IN:
return {
...state,
...action.payload
}
default:
return state
}
}
const initialState = {
users: {
isSignedIn: false,
role: '',
uid: '',
userName: ''
}
};
export default initialState
export const SIGN_IN = 'SIGN_IN';
export const signInAction = (userState) => {
return {
type: 'SIGN_IN',
payload: {
isSignedIn: true,
role: userState.role,
uid: userState.uid,
userName: userState.userName
}
}
};
signInActionの返り値であるオブジェクトをreducersでより簡潔に記述するため、またプロパティが失われないようにするためにスプレッド構文を使ってマージしていたことがわかりました。
参考

まとめ
この記事ではスプレッド構文についてまとめました。
初めて聞いた記法だったのですが、勉強していく上で便利なものだと気付かされました。
是非、いいねやコメントをお願いします。
コメント