コールバック関数
コールバック関数 とは
他の関数に渡して呼んでもらう関数 = コールバックを書く。本レッスンでは、コールバック関数 の基本から実際の使いどころまでを整理し、現場で迷わず使える形に落とし込みます。
コールバック関数とは
JavaScript を使い始めると、関数の引数に また別の関数 を渡す場面によく出会います。代表的なのは 配列 の map 、 filter 、 forEach 、それから setTimeout や addEventListener などです。このように 他の関数に渡される関数 を コールバック関数 (callback function) と呼びます。
コールバックとは
あとで呼んでねという意味で、親の関数が子の関数を都合のいいタイミングで呼び出してくれるイメージです。
コールバックを使うと、 処理の流れ と 具体的な処理内容 を切り離せます。例えば「配列をループしてくれる仕組み」と「各要素をどう扱うか」を別の関数に分けて書ける、ということです。これが JavaScript を表現力豊かな言語にしている大きな理由の一つです。
一番シンプルな例
Array.prototype.forEach は典型的なコールバックの使い手です。
JavaScript
const fruits = ['apple', 'banana', 'cherry'];
fruits.forEach((fruit) => {
console.log(`I like ${fruit}`);
});forEach は配列を順番にループしてくれる関数で、各要素を引数にしてコールバックを呼び出します。コールバックの中身を変えれば、ループ部分はそのままで 処理だけ差し替え ができます。
JavaScript
const doubled = [];
fruits.forEach((fruit) => doubled.push(fruit + fruit));
console.log(doubled); // ['appleapple', 'bananabanana', 'cherrycherry']map で値を加工する
map も 配列 メソッドの中で最重要級のコールバック使用例です。元の配列の各要素にコールバックを適用し、 新しい配列 を作って返します。
JavaScript
const nums = [1, 2, 3, 4];
const doubled = nums.map((n) => n * 2);
console.log(doubled); // [2, 4, 6, 8]コールバックの中身を n * 2 から n * n に変えれば二乗の配列が得られます。 ループ の構造を書かずに 何をしたいか だけ書ける、これがコールバックのうれしさです。
mapの戻り値は新しい配列です。元の配列は変更されません。forEachは戻り値がundefined、mapは戻り値が新しい配列、と覚えましょう。
コールバックを受け取る関数を自分で書く
map や filter はあらかじめ用意されたメソッドですが、 自分で コールバックを受け取る関数を書くこともできます。
JavaScript
function applyAll (arr, fn) {
const result = [];
for (const item of arr) {
result.push(fn(item));
}
return result;
}
console.log(applyAll([1, 2, 3], (n) => n * 10)); // [10, 20, 30]applyAll は 配列 と コールバック を引数で受け取り、ループの中でコールバックを呼んで結果を集めています。実質 map の手作り版です。これを書けるようになると、コールバックの仕組みが体に染み込みます。
関数を
第一級オブジェクトとして扱える、というのがJavaScriptの重要な特徴です。関数を変数に入れたり、引数に渡したり、戻り値に使ったりできます。
よくある間違い
以下のとおりです。
- コールバックを呼ぶつもりが
fnだけ書いてしまい呼ばれない (fnで値を取り出すにはfn()のように()が必要) fn(item)の代わりにfnを()付きで先に呼んでしまう (addEventListener('click', handler())のようなアンチパターン)mapの中でreturnを書き忘れて全要素undefinedの配列ができる
JavaScript
const arr = [1, 2, 3];
const bad = arr.map((n) => { n * 2 });
console.log(bad); // [undefined, undefined, undefined]アロー関数で
{}を使うときはreturnが必要 — このパターンはコールバックでも頻発します。
やってみよう
配列 arr を受け取り、 map を使って各要素を 2倍 + 1 に変換した新しい配列を返す関数 applyCallback を書きましょう。中身では map に アロー関数のコールバック を渡します。元の配列を破壊せず、新しい配列を return するのがポイントです。
よくある質問
Q. ブラウザと Node.js で動作は変わりますか?
A. JavaScript の構文・組み込み機能(配列・文字列・Promise 等)はどちらでも同じです。違いは DOM API(ブラウザ専用)と fs などのファイル系(Node 専用)など、実行環境固有の機能です。コアロジックは両方で動くため、テストもしやすくなります。
Q. ES6 以降の新機能は使っても大丈夫ですか?
A. 現代のブラウザ・Node.js は ES2020 以降の機能をほぼサポートしています。古い IE 等を対象にする必要が無ければ、let/const、アロー関数、分割代入、async/await を積極的に使ってください。トランスパイル(Babel/Vite)が必要なケースは年々減っています。
Q. TypeScript に進む価値はありますか?
A. 型情報があるとリファクタやエディタ補完が劇的に効くため、規模が大きくなるなら TypeScript への移行を強くおすすめします。最初は any を許容しつつ徐々に型を付ければ、JS の知識をそのまま活かせます。
次のレッスン
次は クロージャでカウンタ で、他の関数に渡して呼んでもらう関数 = コールバックを書く を学びます。
事前確認 — 進む前に次の 3 つができることを確認しましょう。
- コールバック の要点を自分の言葉で説明できる
- このレッスンの最小コード (または操作手順) を見ずに書ける
- 練習問題やクイズで間違えた箇所を読み直して理解した
理解度チェック (30 秒)
Q. コールバック とは何か、1 文で説明してください。
A. 本文の「このレッスンで分かること」または冒頭の説明文を見直し、自分の言葉で要約できれば OK。詰まったら本レッスンの最初の H2 セクションを読み返してみましょう。
関連レッスン
要件
- Array.prototype.map を使う
- map にコールバック関数 (アロー関数) を渡す
- 各要素を 2 倍 + 1 にした新しい配列を return する
入出力例
test-cases.txt
applyCallback([1,2,3]) → [3,5,7]
applyCallback([]) → []
applyCallback([0]) → [1]
applyCallback([-1,5,10]) → [-1,11,21]