関数は値です。 数値や文字列と同じように扱えます。
変数に入れ、配列に並べ、オブジェクトの値にできます。 引数として渡すこともできます。
map() に渡しているもの
この2つは同じことをしています。
map() は「配列の各要素に、渡された関数を適用する」だけの関数です。
何をするかは、渡す側が決めます。
関数を受け取る関数、または関数を返す関数を高階関数と呼びます。
map() filter() sort() は全部そうです。
→ 配列を変換する・絞り込む
関数を返す
第2回で見た形です。
「先に決まるもの」を固定した関数を作れます。 これを部分適用と呼びます。
map() にそのまま渡せます。
const double = (n) => n * 2;
try {
[1, 2, 3].map(double(0));
} catch (error) {
console.log(error.name);
}既存の関数を包む
関数を受け取って、機能を足した新しい関数を返します。
console.log(['1', '2', '3'].map(parseInt));元の add は書き換えていません。 包んだ新しい関数を作っただけです。
...args で引数を全部受けて、そのまま渡しています。
だから、どんな関数にも使えます。
→ 関数の引数 — 既定値・可変長・分割代入
記録・計測・再試行・キャッシュは、この形で足せます。 → 失敗したら再試行する
繋げる
const user = {
name: 'あ',
greet() {
return this.name;
},
};
const fn = user.greet;
console.log(fn());twice(add1) が「2回足す関数」になり、それをさらに twice() に渡せます。
関数を組み合わせて新しい関数を作れるのが、値である利点です。
よくある間違い
呼び出しと参照を取り違える
double(0) はその場で呼んだ結果(0)です。関数ではありません。
map() はそれを呼ぼうとして落ちます。
Node 22.22.3 の文言は「number 0 is not a function」。処理系によって変わります。 → TypeError: x is not a function
渡すときは () を付けません。
引数が3つ渡ることを忘れる
map() はコールバック関数に (値, 添字, 配列) の3つを渡します。
parseInt(値, 添字) として呼ばれ、添字が何進法かの指定になってしまいます。
関数名をそのまま渡すときは、第2・第3引数をどう扱うか確かめてください。
メソッドを取り出して渡す
取り出した時点で user との繋がりが切れています。
this は呼ばれ方で決まるからです。
bind() で結んでおけば渡せます。
まとめ
- 関数は値。変数・配列・オブジェクト・引数のどこにでも置ける
map()に渡しているのは値としての関数- 関数を返せば、先に決まるものを固定した関数が作れる
- 包めば、元を書き換えずに機能を足せる
- 渡すときは
()を付けない map()は3つの引数を渡す。map(parseInt)と書かない- メソッドを取り出すと
thisが外れる。渡すならbind()
この連載はここまで
関数を作り、変数の見える範囲を知り、値として扱うところまで来ました。 ここから先は、必要になったときに引ける形でまとめてあります。
- 関数の引数 — 既定値・可変長・分割代入
… 既定値が
nullでは働かない理由、lengthが数えないもの - なぜ this は呼び方で変わるのか … アロー関数だけが例外である仕組み
- 配列を変換する・絞り込む
…
map()とfilter()を繋げて書く - Promise — then / catch / finally と async / await … 非同期の処理も、関数を渡して組み立てる