関数を返す関数
このレッスンで分かること
- 既にある関数を材料にして、新しい関数を組み立てられます
- 組み立てた関数は
mapにそのまま渡せます
組み合わせのぶんだけ、無名関数を書き直している
作品タイトルを表示用に整える処理が 2 つあるとします。前後の空白を落とす関数と、長すぎるときに切る関数です。
JavaScript
const titles = [" プロフィールサイト ", " 自己紹介カード "];
function trimTitle(text) {
return text.trim();
}
function cutTitle(text) {
return text.length > 6 ? text.slice(0, 6) : text;
}
console.log(titles.map(function (text) {
return cutTitle(trimTitle(text));
}));動きますが、map に渡すたびに無名関数で包み直しています。順番を入れ替えたい、片方だけ当てたい、と言われるたびに同じ入れ子を書き直すことになります。
2 本の関数から 1 本の関数を作る
包み直す作業そのものを関数にします。戻り値が関数になっている関数です。
JavaScript
function pipeTwo(first, second) {
return function (value) {
return second(first(value));
};
}
const cleanTitle = pipeTwo(trimTitle, cutTitle);
console.log(titles.map(cleanTitle));pipeTwo が返すのはただの関数なので、map にそのまま渡せます。first と second はクロージャに閉じ込められていて、外から差し替えられません。
順番が結果を決めます。
pipeTwo(trimTitle, cutTitle)とpipeTwo(cutTitle, trimTitle)は別物です。前後に空白が付いた文字列を渡すと、後者は空白ごと 6 文字に切ってしまいます。
3 本以上をつなげたいときは、出てきた結果を次の入力に渡していくだけです。
JavaScript
let text = " プロフィールサイト ";
for (const fix of [trimTitle, cutTitle]) {
text = fix(text);
}
console.log(text); // プロフィールサtext を上書きしながら順に当てています。空の配列を渡すと 1 回も回らず、値がそのまま残ります。これは「何もしない変換」として扱えるので、件数を数えて分岐する必要がありません。
名前で処理を選ぶ
どの処理を当てるかが文字列で届く場合は、名前と関数の対応表を用意します。
JavaScript
const decorators = {
bracket: function (text) { return "[" + text + "]"; },
arrow: function (text) { return "> " + text; }
};
const chosen = decorators["bracket"];
console.log(chosen("プロフィールサイト")); // [プロフィールサイト]decorators["bracket"] で取り出しているのは関数そのものです。ここで括弧を付けて decorators["bracket"]() と書くと、その場で実行された結果が入ってしまいます。取り出すときは括弧を付けない、と覚えてください。
対応表があれば、当てる処理とその順番を ["bracket", "arrow"] のような文字列の配列で受け取れます。処理の順番がデータになる、ということです。並び順を画面のフォームから受け取ることもできます。
よくある間違い
- 関数を返すつもりで値を返す —
return second(first(value));をreturn function (value)の外に書くと、その時点ではvalueがまだ無いので落ちます。組み立てる側が返すのは値ではなく関数です - 対応表から取り出すときに括弧を付ける — 実行結果が入ってしまい、渡し先で「関数ではない」と怒られます
- 組み立てた関数の中で外の変数を書き換える — 組み立てた関数は要素の数だけ呼ばれるので、呼んだ回数によって結果が変わります。材料にする関数は、外を触らないものだけにそろえます
要件
- 関数名は buildTransform とし、引数は stepNames (文字列の配列) と values (数値の配列) の 2 つにする
- double は 2 倍、addTen は 10 を足す、square は 2 乗する。工程名と処理の対応を関数の中に用意する
- 工程名の配列から 1 本の関数を組み立てて返す関数を定義し、その戻り値を使って values を変換する
- 戻り値は values と同じ長さの数値の配列にする。stepNames が空のときは values の値をそのまま返す