🤔

スプレッド構文を理解する

2022/09/18に公開約3,100字

Next.jsを勉強している中でよくスプレッド構文が使用されるが、あまりよく理解していなかった為、まとめてみることにしました。

まず破壊的メソッド・非破壊的メソッドとミュータブル・イミュータブルについて理解をしてから、スプレッド構文の使い方を確認していきました。

スプレッド構文とは

...hogeなどの形で記述して、配列やオブジェクトの要素を大括弧[]や中括弧{}を外して展開してくれたりする。

破壊的メソッド・非破壊的メソッドとは

破壊的メソッド

配列の内容や配列の要素の順番を変更してしまいます。
最近のJavascriptで使用することはよくない。
これを避けるためにスプレッド構文を使用する。

破壊的メソッド一覧

メソッド名 返り値
splice() 取り除かれた要素を含む配列
push() 変更後の配列のlength
unshift() 変更後の配列のlength
pop() 配列の末尾の値
shift() 配列の先頭の値
sort() ソートした配列
reverse() 反転した配列
copyWithin() 変更後の配列
fill() 変更後の配列

非破壊的メソッド

非破壊的メソッドは、操作に配列の変更をともなわないメソッドです。

ミュータブル・イミュータブルとは

ミュータブル・イミュータブルとは、値を作成した後にその値を変更できるかどうか。

  • ミュータブル
    値を作成した後に変更できる。

  • イミュータブル
    値を作成した後に変更できない。

Javascriptにおいて、文字列や数値はデフォルトでイミュータブル。
ただし、配列とオブジェクトに関しては、デフォルトでミュータブル。

破壊的メソッドをつかってしまうと、ミュータブルなものとして扱ってしまうことになるので、スプレッド構文を使用してイミュータブルにしていくことが分かった。

スプレッド構文の使い方

配列の展開

まずはスプレッド構文を使用してコンソールに出力したときの違いを確認してみる。

const arr1 = [1,2,3]
console.log(arr1)

const arr2 = [1,2,3]
console.log(...arr2)

出力結果

上:arr1
下:arr2

スプレッド構文を使用すると、配列だった値が実際の数字の1と2になっていることが確認できます。
配列の中身を順番に処理をして展開をしてくれていることが分かりました。

では次に2つの引数を受け取り、その合計を出力してくれる関数を例に違いをみていきます。

const arr1 = [1, 2];
const arrFunc = (arr1, arr2) => console.log(arr1 + arr2);

arrFunc(arr1[0], arr1[1]);
arrFunc(...arr1);

出力結果


こちらの出力結果はどちらも3になります。
スプレッド構文を使用した記述の方が記述量も減り、すっきり書けてることが分かります。

配列をまとめる

6つの要素をもった配列を用意して、分割代入をした値を出力してみます。

const arr = [1,2,3,4,5,6]
const [arr1,arr2, ...arr3] = arr

console.log(arr1);
console.log(arr2);
console.log(arr3);

出力結果

arr1は1
arr2は2
スプレッド構文を使用したarr3に関しては、残りの3、4、5、6が1つの配列としてまとめて出力できていることがわかります。

配列のコピー

arr1と同じ要素をもった新しい配列arr2を生成する。

const arr1 = [1, 2, 3, 4, 5, 6];
console.log(arr1);

const arr2 = [...arr1];
console.log(arr2);

出力結果

arr1とarr2の2つとも同じ出力結果なのが分かります。

=でのコピーがよくないのはなぜか?

=ではなく、スプレッド構文によって配列をコピーすると参照元の値が変更されてしまうことを防ぐことができます。
どういうことか、挙動を確認してみます。

まずはarr1をarr3にコピーをしてコンソールで確認してみます。

const arr1 = [1, 2];
const arr3 = arr1;

console.log(arr3);

出力結果

arr3はarr1と同じであることが分かります。

次にあとからarr3の最初の要素を1から100に変更してみます。

const arr1 = [1, 2];

const arr3 = arr1;

arr3[0] = 100;

console.log(arr3);
console.log(arr1);

出力結果

上:arr3
下:arr1

出力結果を確認してみると、変更していない参照元のarr1の中身まで影響を受けてしまっていることが分かります。
このようなことが起こってしまうと不具合の原因になってしまうこともあるため、基本的にスプレッド構文を使用したコピーをしたほうがよいということが分かります。

配列の結合

arr1とarr2を結合したarr3を出力してみます。

const arr1 = [1,2];
const arr2 = [3,4];

const arr3 = [...arr1, ...arr2];
console.log(arr3);

出力結果

arr3の出力結果を確認してみると、arr1とarr2が結合されてることが分かります。

Discussion

ログインするとコメントできます