コールバック関数
このレッスンで分かること
JavaScriptでは関数を値として、変数に入れたり引数に渡したりできますfnは関数そのもの、fn()は呼び出した結果です。渡すのはfnです
中の 1 行だけが違う関数を、何本も書くことになる
同じ形の関数を、中の 1 行だけ変えて何本も書く場面はすぐにやってきます。
JavaScript
function shout(text) {
return text + "!!!";
}
function polite(text) {
return text + " 様";
}処理そのものを渡せたら、受け取る側は 1 本で済みます。JavaScript の関数には、他の入門言語にはあまり無い特徴があります。関数が値として扱えることです。数値や文字列と同じように変数に入れられますし、引数として渡せます。
JavaScript
function decorate(text, fn) {
return fn(text);
}
console.log(decorate("山田 太郎", shout));
// => 山田 太郎!!!
console.log(decorate("山田 太郎", polite));
// => 山田 太郎 様decorate は、受け取った fn を中で呼んでいるだけです。何をするかは呼ぶ側が決めます。渡す関数を差し替えれば、decorate を 1 文字も直さずに振る舞いが変わります。この、あとで呼んでもらうために渡す関数をコールバック関数と呼びます。
その場でしか使わないなら、変数に入れずに直接書けます。
JavaScript
console.log(decorate("山田 太郎", (text) => text + " さん"));
// => 山田 太郎 さん前のレッスンでアロー関数を学んだのは、この書き方のためでもあります。使い捨ての小さな処理を、その場で矢印 1 つで書ける。だからコールバックとアロー関数はいつも一緒に登場します。
丸カッコを付けた瞬間、渡すものが変わる
コールバックで最も多い事故が、渡すときに呼び出してしまうことです。
| 書き方 | 意味 |
|---|---|
shout | 関数そのもの |
shout("公開中") | 呼び出した結果。ここでは文字列 |
shout はレシピ、shout("公開中") は作った料理です。レシピを渡してほしい相手に料理を渡すと、受け取った側は fn(text) と呼ぼうとして、文字列は呼べないというエラーになります。
JavaScript
decorate("山田 太郎", shout); // OK 関数そのものを渡している
decorate("山田 太郎", shout()); // NG その場で実行され、戻り値が渡る何が渡ってくるかは、呼ぶ側が決める
コールバックを呼ぶのは受け取った側なので、引数を渡すのも受け取った側です。
JavaScript
function twice(text, fn) {
return fn(text) + "/" + fn(text);
}
console.log(twice("公開中", (t) => "[" + t + "]"));
// => [公開中]/[公開中]コールバックに何が何番目で渡ってくるかは、渡し先の関数の仕様しだいです。自分で書いた関数なら自分で決められますが、用意されている関数に渡すときは、必ず確かめてから受け取る引数を書いてください。
よくある間違い
- コールバックの中で
returnを書き忘れる —(text) => { text + " さん"; }はundefinedを返します。{ }を書いたらreturnが要る、というアロー関数のルールがそのまま効きます - 渡ってくる値と合わない名前を付ける — 要素が渡ってくるのに
indexという名前で受けても、エラーにはなりません。動いてしまうぶんだけ、読む人は確実に混乱します
要件
- 配列とコールバックを受け取る関数 applyAll(arr, fn) を用意すること
- applyToWorks は applyAll にアロー関数のコールバックを渡すこと
- コールバックは要素とインデックスを受け取り、
連番. 作品名の文字列を返すこと - applyToWorks は文字列の配列を return し、空配列なら空配列を返すこと
入出力例
applyToWorks(["プロフィールサイト","自己紹介カード","スキル一覧の表"]) → ["1. プロフィールサイト","2. 自己紹介カード","3. スキル一覧の表"]
applyToWorks(["プロフィールサイト"]) → ["1. プロフィールサイト"]
applyToWorks(["A","B"]) → ["1. A","2. B"]
applyToWorks([]) → []ヒント
編集 ゆめさく編集部