UXPに備えてモダンなJSの書き方に慣れる(array,objectメソッド)

javascript

モダンなjsを書く方にはもう当たり前ですがECMA5でarrayメソッドがたくさん追加されました。forEach,map,filter,some,every,reduce等。アロー関数と組み合わせるとECMA3でfor文で書いていたほとんどのコードをかなり省略化できます。慣れるともはやfor文自体使う頻度がかなり減るでしょう。同様にObjectのプロパティを列挙する構文はECMA3までだとfor~in文しかありませんでした。しかしECMA2015以降これらのコードも簡略化できるように新しいメソッドが追加されました。今回繰り返し処理の構文を紹介します。

array メソッド

前述の通りECMA5で多くのarrayメソッドが追加されました。for文の様にindexの変数を宣言したり配列の長さをlengthで調べなくても勝手に全ての値を反復してくれるので便利です。以下forEachの例になります。

forEachメソッドはコールバックで各配列の値、indexを引き受けつつ関数を実行します。引数は見ての通りvalue,index,arrayとなっており、valueが配列の各値、indexが値のindex,arrayは配列そのものを引き受けます。valueもindexも呼び出される事に異なる値が返ってきますがarrayは配列そのものを返すので常に不変です。このあたりは全てのarrayメソッドで一部例外を除いて共通となります。この通り一々indexを変数で宣言しなくても配列の値を順番に取り出せます。ただ関数を実行するだけで新しい配列を返さないforEachだとちょっとわかりづいかもしれません。というわけで次はどうでしょう。

map

mapメソッドはforEach同様各配列の値をコールバックで引き受けつつ関数を実行して返ってきた新しい値をそのまま新しい配列の値として返します。例えば以下のサンプルはどうでしょう。

コールバックの引数のxで配列の値を引き受けつつアロー関数で二倍にした値を返しています。(アロー関数は一行でまとめる時{}とreturnと引数が一つの時に()を省略できる。)for文のように特にindex変数の宣言も必要なければlengthで配列の長さを調べる必要も無く配列内の値を順番に処理して新しい配列を作れました。これをECMA3で書くと以下のようになります。

このような簡単な関数でした3行程必要だったコードがアロー関数と組み合わせるとなんと一行で済んでしまいました。ちなみに関数をそのまま引数に渡すことも可能です。

勿論number型に限らずstringでもなんでも関数処理できます。

ちなみ今回紹介するメソッドは全て非破壊的(元の配列はそのままに変更しない。)です。唯一forEachのみ新しい配列を返さないでただ反復するのみです。この辺までが各arrayメソッドの共通部分になります。それでは他メソッドも見ていきましょう。

filter

filterメソッドは関数内で実行した値を元に返ってきた結果がtrueだったら配列の値を残してfalseだったら値を取り除きます。配列内の余計な値を取り除きたい場合に使用します。

some

someメソッドは関数を実行して一つでも関数がtrueを返せばtrue,全てfalseを返せばfalseを返します。配列内に条件に当てはまる値が含まれているかどうか調べるのに有効です。

しかし単に配列内に特定の値が入っているかどうかならincludesメソッドも使えます。

これは配列の中に引数で渡した値が一つでもあればtrue,なければfalseを返します。someより簡単に書けますね。そのためsomeは何かしら関数処理を実行する必要がある場合のみに使うのがいいでしょう。

every

everyメソッドはsomeと似ていますがコールバック関数が一つでもfalseを返せばfalse、全てtrueを返す事でtrueになります。

配列内に好ましくない値が入っているか調べる場合に有効です。

reduce

reduceメソッドは数あるarrayメソッドの中でも最強のメソッドともよく言われます。一般的にreduceメソッドは配列の値を一つの値にまとめるメソッドであると説明されます。

配列の全ての数値を足して35の値が返ってきました。reduceメソッドのみ各、値を合計した値を最初の引数に返すので引数は(合計値、value(各配列の値)、index、array(配列そのもの))となります。

ただし最初のindexのコールバックはとばしてしまいます。これは最初の配列の値をそのまま合計値として記録するためです。reduceメソッドは関数だけでなく初期値を第二引数に渡せます。これを渡すと0 indexから配列処理をします。

初期値を0としてそこから合計値を順に足しています。勿論number型以外も可。

それでここまでが教科書的なreduceメソッドの説明になります。しかしこのreduceメソッド、関数でobjectでも多重配列でも返すようにすればobjectでもarrayでも返すことが可能です。つまり配列をオブジェクトとして返す、もしくは新しい配列にも。おそらく当初は誰でも配列をオブジェクトに組み込み直す場合はforEachを使うと思います。

しかし関数の外で一々空のオブジェクトや空の配列を宣言するのはあまり見栄えが良くありません。これをreduceメソッドで行います。

合計値をobjectやarrayとして渡すことで新しいobject,arrayを返すことが可能です。forEachはただの繰り返し処理なので新しい値を返すわけでもないので基本配列をベースにオブジェクトや多重配列を作りたい場合はmapやreduceを使い、それでもダメならforEach、それでもダメなら最後にfor文で回してみるという具合でしょうか。ちなみにarrayメソッドはメソッドチェーンでつなぐことも可能です。

ある程度込み入った処理も数行で済ませることも可能です。

Objectの繰り返し処理

ECMA3まではfor in文がオブジェクトプロパティを列挙する主な構文でした。

最新のjsだとオブジェクトのkey、valueを簡素に列挙できます。正確にはObjectを簡単に配列に変換できるということでしょうか。まずはObject.valuesメソッドでオブジェクトのプロパティの値を列挙してみます。

引数に渡したオブジェクトを配列として返します。返ってきた配列オブジェクトはarrayメソッドも使えるのでforEachで値を列挙しています。勿論keyの列挙も可能。その場合keysメソッドを使用します。

Objectのkeyとvalue、両方を列挙したい時も専用のメソッドがあります。Object.entriesです。

keyとvalueを多重配列として返します。配列の中の配列にkeyが一番目、valueが二番目に格納されています。これをforEach等で列挙する場合は分割代入で引き受けたkeyとvalueを簡素に列挙できます。またforEach同様他のメソッドもチェーンメソッドでつないで新しい配列を返すことが可能。

勿論keysでもvaluesでもチェーンメソッドで列挙後に結果をそのまま返せます。

その他個人的にあまり使ったことないですが二重配列、ECMA2015から追加されたMapオブジェクトをオブジェクトに変換するfromEntriesもあります。

ECMA2015以降も便利なarrayメソッドが次々に追加されています。またObject.entries等はECMA2017で追加されたメソッドなので古いCEP環境などで使用する場合は必ずbabel等を噛ませてください。

 

Beer 寄付してサイトを応援する。