コールバック関数って何者?
コールバック関数は、
「あとで呼び出してもらうために“渡しておく関数”」 です。
ふつうは「関数を“呼び出す”側」と「呼び出される側」がはっきり分かれていますが、
コールバックでは「関数を“引数として渡す”」ことで、
「いつ・どんなタイミングで実行するか」を相手に任せます。
一言でいうと、
「関数を値として渡して、“終わったらこれやってね”と予約しておく仕組み」 です。
まずは超シンプルなコールバックの例から
「終わったら呼んでね」をコードにするとこうなる
「作業が終わったら教えてね」というイメージで考えてみます。
function doTask(callback) {
console.log("タスクを実行中...");
callback(); // 終わったタイミングで呼び出す
}
function afterTask() {
console.log("タスクが終わりました!");
}
doTask(afterTask);
JavaScript流れを言葉で追うと、
afterTaskという関数を定義doTaskに「引数として」afterTaskを渡すdoTaskの中でcallback()として呼び出す- そのタイミングで
afterTaskが実行される
ここが重要です。
コールバック関数とは「自分で呼ぶのではなく、“誰かに呼んでもらうために渡す関数”」 です。doTask(afterTask) の時点では afterTask は「実行されていない」。
実際に実行されるのは、doTask の中で callback() と呼ばれた瞬間です。
無名関数をその場で渡すパターン
わざわざ名前をつけずに書くことも多い
さっきは afterTask に名前をつけましたが、
実務では「その場で関数式(またはアロー関数)を書いて渡す」ことが多いです。
function doTask(callback) {
console.log("タスクを実行中...");
callback();
}
doTask(function () {
console.log("タスクが終わりました!(無名関数)");
});
JavaScriptアロー関数ならこう。
doTask(() => {
console.log("タスクが終わりました!(アロー関数)");
});
JavaScriptここで渡している function () { ... } や () => { ... } が、
まさに「コールバック関数」です。
「終わったらこれやってね」という“処理そのもの”を、
その場で書いて渡しているイメージです。
コールバック関数が本領発揮するのは「非同期処理」
「いつ終わるか分からない」からこそ“終わったタイミングで呼ぶ”
例えば、1秒後に何かをしたいとき。
setTimeout(function () {
console.log("1秒経ちました");
}, 1000);
JavaScriptsetTimeout の第1引数がコールバック関数です。
「1秒後にこの関数を呼んでね」と予約しているわけです。
アロー関数で書くとこう。
setTimeout(() => {
console.log("1秒経ちました");
}, 1000);
JavaScriptここが重要です。
非同期処理(時間がかかる処理)では、「終わった瞬間に何をするか」を
コールバック関数として渡す、というパターンが基本になります。
例えば、サーバーからデータを取ってくる処理を、
昔ながらのコールバックスタイルで書くとこうなります。
function fetchData(callback) {
setTimeout(() => {
const data = { message: "サーバーからのデータ" };
callback(data); // 取れたデータを渡して呼び出す
}, 1000);
}
fetchData((result) => {
console.log("受け取ったデータ:", result);
});
JavaScriptfetchData は「いつデータが取れるか分からない」。
だから「取れたらこの関数を呼んで、そのときに結果を渡してね」とする。
これがコールバックの典型パターンです。
コールバック関数の「引数」として結果を受け取る
「終わったら呼ぶ」だけじゃなく「結果も渡す」
さっきの fetchData をもう一度見ます。
function fetchData(callback) {
setTimeout(() => {
const data = { message: "サーバーからのデータ" };
callback(data);
}, 1000);
}
fetchData((result) => {
console.log("受け取ったデータ:", result);
});
JavaScriptここでのポイントは、
callback(data) として「結果 data を引数に渡している」
呼び出し側では (result) => { ... } として「その結果を受け取る」
という対応関係です。
つまり、
「非同期処理の結果を、コールバック関数の引数として渡す」
という形になっています。
これにより、
「いつ終わるか分からない処理」
「終わったらやりたい処理」
「その処理に渡したい結果」
をきれいに分離できます。
コールバック関数がよく使われる標準的な場面
配列メソッド(forEach, map, filter など)
配列メソッドは、コールバック関数の練習に最適です。
forEach の例:
const numbers = [1, 2, 3];
numbers.forEach((n) => {
console.log("要素:", n);
});
JavaScriptここで (n) => { ... } がコールバック関数です。
配列の各要素に対して、順番に呼び出されます。
map の例:
const numbers = [1, 2, 3];
const doubled = numbers.map((n) => {
return n * 2;
});
console.log(doubled); // [2, 4, 6]
JavaScriptmap は「各要素に対してコールバックを実行し、その戻り値を集めて新しい配列を作る」メソッドです。
ここが重要です。
配列メソッドは「配列が“いつ・どの順番で”コールバックを呼ぶかを決めてくれていて、
自分は“要素1つに対して何をするか”だけを書けばいい、という分業になっている。
これが「コールバックの世界観」です。
コールバック関数の“本質”を言語化しておく
「制御の流れを相手に渡す」
普通の関数呼び出しはこうです。
const result = doSomething();
use(result);
JavaScript「doSomething を呼ぶ → 結果を受け取る → 自分で次の処理をする」
という“自分主導”の流れです。
コールバックを使うと、こうなります。
doSomethingAsync((result) => {
use(result);
});
JavaScript「doSomethingAsync に“終わったらやる処理”を渡す →
あとは doSomethingAsync が好きなタイミングでそれを呼ぶ」
つまり、
「いつ実行するかの主導権(制御の流れ)を、相手に渡している」
ということです。
ここがコールバックの本質です。
だからこそ、非同期処理やイベント処理と相性がいい。
「いつ起きるか分からないこと」に対して、
「起きたときにやること」をあらかじめ渡しておけるからです。
初心者が最初に意識しておきたいポイント
「関数を“実行せずに渡す”感覚をつかむ
よくあるつまずきがこれです。
doTask(afterTask()); // ← これは NG
JavaScriptこう書くと、afterTask はその場で実行されてしまい、doTask には「戻り値」が渡されます(たいてい undefined)。
正しくはこうです。
doTask(afterTask); // 関数そのものを渡す
JavaScriptもしくは、
doTask(() => {
console.log("終わったよ");
});
JavaScriptここが重要です。
「afterTask() は“実行”、afterTask は“関数そのもの”」
コールバックとして渡したいのは“関数そのもの”の方です。
まとめ:コールバック関数の基礎で本当に押さえてほしいこと
コールバック関数は、
「あとで呼び出してもらうために、引数として渡す関数」。
特に大事なのは次の感覚です。
- 「関数を値として渡す」=
doSomething(callback) - 「渡された関数を呼ぶ」=
callback() - 非同期処理では「終わったらこの関数を呼んで、そのとき結果を引数で渡してね」という形になる
- 配列メソッド(forEach, map, filter)は、コールバックの超良い練習台
まずは、
function doTask(callback) {
console.log("タスク中...");
callback("完了しました");
}
doTask((message) => {
console.log("コールバック:", message);
});
JavaScriptこのくらいのコードを、自分の手で何度か書いてみてください。
「関数を渡す」「渡された関数を呼ぶ」
この2ステップが体に馴染んだ瞬間、
非同期処理・イベント処理・配列操作など、
JavaScript の“気持ちいい書き方”が一気に見えてきます。

