前回は for...of で1つずつ処理しました。
今回は、その中でも特に多い「全部に同じ加工をして、新しい配列を作る」を短く書きます。
ループで書くとこうなる
値段の配列から、税込み価格の配列を作ります。
やっていることは3つです。空の配列を用意し、回して、push() する。
この形はとても多く出てくるので、専用の書き方があります。
map なら1行
map() は、1つ1つを関数に通して、その戻り値を集めた新しい配列を返します。
空の配列も push() も要りません。
上のコードは書き換えて実行できます。* 1.1 を * 1.3 にしてみてください。
要素の数は変わりません。 3件入れたら3件返ります。
filter で絞る
数を減らしたいときは filter() です。
filter() に渡す関数は、残すかどうかを返します。
true になった要素だけが集まります。
| 何をするか | 要素の数 | |
|---|---|---|
map() |
変換する | 変わらない |
filter() |
絞る | 減ることがある |
変換と絞り込みは別の仕事です。 map() で要素を減らすことはできません。
繋げて書く
map() も filter() も配列を返すので、そのまま次に繋げられます。
これをメソッドチェーンと呼びます。
const prices = [100, 200];
const withTax = prices.map(price => {
Math.round(price * 1.1);
});
console.log(withTax);絞ってから変換するほうが、変換の回数が減ります。 上の例では4件のうち2件しか計算していません。
読むときは上から順に追ってください。「200円以上を残して、税込みにする」と読めます。
元の配列は変わらない
map() も filter() も非破壊的メソッドです。
前回出てきた push() や pop() とは違います。
呼んだだけでは何も起きません。戻り値を受け取る必要があります。
途中で空になっても落ちない
filter() が1件も残さなかったとき、返るのは空の配列です。
null ではないので、そのまま次に繋げても止まりません。
第1回で見た「範囲の外を読むと undefined」とは違い、ここは安全です。
繋げた先で落ちる心配をしなくて構いません。
よくある間違い
{} で囲んだのに return を書き忘れると、全部 undefined になります。
エラーになりません。静かに undefined が並びます。
{} を外すか、return を書けば直ります。
まとめ
map()… 1つ1つを変換して新しい配列を作る。数は変わらないfilter()… 残すものを選ぶ。数は減ることがある- どちらも元の配列を変えない。戻り値を受け取る
- 繋げられる。絞ってから変換すると無駄が少ない
- 途中で空になっても空配列が返るので落ちない
この連載はここまで
配列を作り、取り出し、繰り返し、変換するところまで来ました。 ここから先は、必要になったときに引ける形でまとめてあります。
- Array.prototype.map() … 穴のある配列での挙動、コールバック関数が受け取る3つの引数
- Array.prototype.filter()
…
find()との違い、filter(Boolean)の書き方 - Array.prototype.reduce() … 配列を1つの値にまとめる。合計・グループ化
- 配列を数値の大きさで並び替える
…
sort()が数値を正しく並べない理由 - 配列から重複を取り除く … オブジェクトの配列で重複が消えない理由