設定を覚えた関数をつくる
このレッスンで分かること
- 設定を先に受け取り、あとは値を渡すだけで済む関数の作りかた
filterやmapにそのまま渡せる形にそろえる意味
数字だけ違う 3 行が並んでいく
第2章で書いた絞り込みを思い出します。作品の配列 works から、公開年で取り出す処理です。
JavaScript
const thisYear = works.filter(function (work) {
return work.year === 2026;
});
const lastYear = works.filter(function (work) {
return work.year === 2025;
});やっていることは同じで、違うのは年の数字だけです。この形のまま条件が増えると、同じ 3 行が数字だけ変えて並びます。あとで「公開済みかどうかも見る」となったとき、直す場所が並んだ数だけ増えます。
コピーした 2 つの塊のうち、違いが数字ひとつだけなら、その数字は引数にできます。引数にできるものを、コピーで済ませないようにします。
設定を先に受け取り、判定そのものを返す
前のレッスンの工場は、書き換わる状態を閉じ込めていました。閉じ込めるものを「変わらない設定」に変えると、判定を作り分ける道具になります。
JavaScript
function createYearFilter(year) {
return function (work) {
return work.year === year;
};
}
const isThisYear = createYearFilter(2026);
const isLastYear = createYearFilter(2025);
console.log(works.filter(isThisYear).length);
console.log(works.find(isLastYear));createYearFilter(2026) の戻り値は関数です。その関数は year が 2026 だったことを覚えているので、あとは作品 1 件を渡すだけで判定してくれます。工場を呼んだ回数だけ設定の箱ができるのは、前のレッスンと同じです。
isThisYear は filter にそのまま渡せます。受け取る側から見れば引数 1 つのただの関数なので、filter でも find でも every でも同じように使えます。ここが要点で、渡し先が呼ぶときの形に、返す関数の引数をそろえておくと、書いた判定がどこでも使い回せます。
| 書きかた | 設定を書く回数 | 呼び出しの形 |
|---|---|---|
| 使う場所ごとに無名関数を書く | 使う場所の数だけ | filter の中に毎回書く |
| 引数を 2 つ取る関数にする | 呼ぶたびに 1 回 | 自分でループを書くことになる |
| 設定を覚えた関数を返す | 作るときの 1 回だけ | filter にそのまま渡せる |
3 行目だけが、設定を書く場所と使う場所を分けられています。
名前が仕様書になる
閉じ込めるのは数値に限りません。単位のような文字列も同じように扱えます。
JavaScript
function createLabeler(unit) {
return function (value) {
return value + unit;
};
}
const toHours = createLabeler(" 時間");
console.log([12, 8, 3].map(toHours)); // ["12 時間", "8 時間", "3 時間"]map に渡すのは toHours という名前だけです。単位を変えたくなったら createLabeler に渡す文字列を直すだけで、map の行はそのままで済みます。isThisYear や toHours という名前が読めれば、中身を開かなくても何をするか分かります。無名関数を並べたコードには、この手がかりがありません。
よくある間違い
- 工場の外に設定を置く — 設定をファイル直下の
letに置いて工場から読むと、2 種類の判定を同時に持てません。あとから書き換えると、先に作った関数の動きまで変わります - 返す関数が受け取る形を間違える — 配列を受け取って中で
filterする関数を返してしまうと、filterに渡したときに 1 件ずつの作品が配列として扱われて壊れます - 判定のたびに工場を呼ぶ —
filterに渡す無名関数の中で工場を呼ぶと、動きはしますが要素の数だけ関数を作り直しています。工場はfilterの外で 1 回だけ呼び、できた関数を渡します
要件
- 関数名は countWorksByThreshold とし、引数は works (作品の配列) と thresholds (数値の配列) の 2 つにする
- 関数の中で、しきい値を受け取って判定関数を返す工場関数を定義する。判定関数は作品 1 件を受け取り true か false を返す
- 判定は work.views がしきい値以上のときに true とする。しきい値ちょうどの作品も数える
- 戻り値は thresholds と同じ長さの数値の配列にする。works が空なら件数はすべて 0 になる