配列の破壊的操作
JavaScriptの配列メソッドには、破壊的なメソッドと非破壊的なメソッドの2種類があります。特に、破壊的なメソッドは注意深く使う必要があります。
非破壊的なメソッド
非破壊的なメソッドは、操作に配列の変更をともなわないメソッドです。たとえば、concatは非破壊的なメソッドです。これは複数の配列を結合するメソッドです。もとの配列は書き換えず、新しい配列を返します。
tsconstnums1 = [1, 2];constnums2 = [3, 4];constall =nums1 .concat (nums2 );console .log (nums1 );console .log (nums2 );console .log (all );
tsconstnums1 = [1, 2];constnums2 = [3, 4];constall =nums1 .concat (nums2 );console .log (nums1 );console .log (nums2 );console .log (all );
非破壊的なメソッドの一覧
非破壊的なメソッドには次のものがあります。
| メソッド | 操作 |
|---|---|
| concat | 2つ以上の配列を結合した配列を返す |
| find | 提供されたテスト関数を満たす配列内の最初の要素を返す |
| findIndex | 配列内の指定されたテスト関数を満たす最初の要素の位置を返す |
| lastIndexOf | 配列中で与えられた要素が見つかった最後のインデックスを返す |
| slice | 配列の一部を切り出して返す |
| includes | 配列に任意の要素が含まれているかをtrueかfalseで返す |
| indexOf | 引数に与えられた内容と同じ内容を持つ最初の配列要素のインデックスを返す |
| join | 全要素を連結した文字列を返す |
| keys | 配列のインデックスをArray Iteratorオブジェクトで返す |
| entries | 配列のインデックスと値のペアをArray Iteratorオブジェクトで返す |
| values | 配列の値をArray Iteratorオブジェクトで返す |
| forEach | 与えられた関数を、配列の各要素に対して一度ずつ実行する |
| filter | 与えられた関数によって実装されたテストに合格したすべての配列からなる新しい配列を返す |
| flat | すべてのサブ配列の要素を指定した深さで再帰的に結合した新しい配列を返す |
| flatMap | 最初にマッピング関数を使用してそれぞれの要素をマップした後、結果を新しい配列内にフラット化する |
| map | 与えられた関数を配列のすべての要素に対して呼び出し、その結果からなる新しい配列を返す |
| every | 列内のすべての要素が指定された関数で実装されたテストに合格するかどうかをテストする |
| some | 配列の少なくともひとつの要素が、指定された関数で実装されたテストに合格するかどうかをテストする |
| reduce | 配列のそれぞれの要素に対してユーザーが提供した「縮小」コールバック関数を呼び出す |
| reduceRight | アキュームレーターと配列のそれぞれの値に対して (右から左へ) 関数を適用して、単一の値にする |
破壊的なメソッド
破壊的なメソッドは、配列の内容や配列の要素の順番を変更する操作をともなうメソッドです。たとえば、pushは破壊的メソッドの1つです。これは、配列末尾に要素を追加します。
tsconstnums = [1, 2];nums .push (3);console .log (nums );
tsconstnums = [1, 2];nums .push (3);console .log (nums );
破壊的なメソッドの一覧
破壊的なメソッドには次のものがあります。
| メソッド | 操作 |
|---|---|
| push | 配列の末尾に要素を追加する |
| unshift | 配列の最初に要素を追加する |
| pop | 配列から最後の要素を取り除き、その要素を返す |
| shift | 配列から最初の要素を取り除き、その要素を返す |
| splice | 要素を取り除いたり、置き換えたり、新しい要素を追加する |
| sort | 配列の要素をソートする |
| reverse | 配列の要素を逆順に並び替える |
| fill | 開始インデックスから終了インデックスまでのすべての要素を、静的な値に変更した配列を返す |
| copyWithin | サイズを変更せずに、配列の一部を同じ配列内の別の場所にシャローコピーして返す |
特に要注意な破壊的なメソッド
reverseメソッドは配列を逆順にした配列を返します。戻り値があるので、一見すると非破壊なメソッドに見えなくもありません。しかし、このメソッドは配列の順番も逆にしてしまうので注意が必要です。
tsconstnums = [1, 2, 3];constnewNums =nums .reverse ();console .log (nums );console .log (newNums );
tsconstnums = [1, 2, 3];constnewNums =nums .reverse ();console .log (nums );console .log (newNums );
PHPのarray_reverse関数はJavaScriptのreverseメソッドと名前が同じですが、PHPのほうは非破壊的な操作です。もとの配列を変更せずに逆順にソートされた配列を新しく生成して返します。
PHPのarray_reversephp$nums = [1, 2, 3];$reversedNums = array_reverse($nums);var_dump($nums);//=> [1, 2, 3]var_dump($reversedNums);//=> [3, 2, 1]
PHPのarray_reversephp$nums = [1, 2, 3];$reversedNums = array_reverse($nums);var_dump($nums);//=> [1, 2, 3]var_dump($reversedNums);//=> [3, 2, 1]
このように、他の言語では非破壊的な配列操作がJavaScriptでは破壊的操作の場合もあります。メソッド名だけで破壊的か非破壊的かを判断せず、各メソッドの使い方をしっかり確認する必要があります。
破壊的なメソッドを安全に使う方法
破壊的なメソッドを非破壊的に使うには、破壊的操作を行う前に、配列を別の配列にコピーします。配列のコピーはスプレッド構文...を用います。
📄️ 配列のスプレッド構文「...」
JavaScript の配列ではスプレッド構文「...」を使うことで、要素を展開することができます。
コピーした配列に対して破壊的操作を行えば、もとの配列が変更される心配が無くなります。
tsconstoriginal = [1, 2, 3];constcopy = [...original ]; // コピーを作るcopy .reverse ();console .log (original ); // 破壊的操作の影響がないconsole .log (copy );
tsconstoriginal = [1, 2, 3];constcopy = [...original ]; // コピーを作るcopy .reverse ();console .log (original ); // 破壊的操作の影響がないconsole .log (copy );
このreverseの例は、コピーと破壊的なメソッドの呼び出しを1行に短縮して書くこともできます。
tsconstoriginal = [1, 2, 3];constreversed = [...original ].reverse ();console .log (original );console .log (reversed );
tsconstoriginal = [1, 2, 3];constreversed = [...original ].reverse ();console .log (original );console .log (reversed );
学びをシェアする
・JavaScriptの配列メソッドには、破壊的なものと非破壊的なものがある
・破壊的なものは、配列に変更を加える
・非破壊的なものは、配列に変更を加えない
・非破壊に思えるメソッドが実は破壊的なこともあるから要注意
・配列をコピーしてから破壊的操作をすると安全
『サバイバルTypeScript』より