コールバック関数とは、別の関数に引数として渡される関数のこと。この渡された関数(コールバック関数)は、外部の関数(親関数)の内部で呼び出される形で実行されます。
// 数値を受け取り、それに10を加えた後、コールバック関数にその結果を渡して実行する関数 function addAndDisplay(number, callback) { let result = number + 10; // 10を加算 callback(result); // 加算結果をコールバック関数に渡して実行 } // 加算結果を受け取り、表示するコールバック関数 function displayResult(result) { console.log('The result after addition is: ' + result); } // addAndDisplay関数を呼び出し、その結果を表示するコールバック関数を渡す addAndDisplay(5, displayResult); // "The result after addition is: 15" を表示
とは言え、定義とコードだけを見せられても少し難しいと思いますので、このページでは簡単なサンプルコードを見ていきながら、徐々にそのイメージが湧きやすくなるようにご説明していきます。
Webエンジニア/Webデザイナーを目指す方であれば知らないと恥ずかしい超・基本知識の1つです。是非最後までご覧ください。
参考 【JavaScript入門】基本文法/基礎文法を5分で
コールバック関数とは?
プログラミングの基本知知識の1つ。コールバック関数はその名の通り「後で呼び出すために渡される関数」だと言えます。特に非同期操作(データを取得する、時間がかかる計算をするなど)を行う際に便利なテクニックの1つで、操作が完了したらその結果に基づいて何かアクションを起こしたいような場合にコールバック関数を使用します。
これは、日常生活の例えを使ってみるとイメージしやすくなるかもしれません。
日常生活での例え 「友人に頼んで後で電話をかけ直してもらう」状況
- 友人への依頼(親関数): 「忙しいから、30分後にもう一度電話して」
- 友人が約束を守り30分後に行動(コールバック関数): 30分後に、友人はあなたに電話をかけ直します。
- 電話を受けた時(コールバック関数の実行): あなたは、電話がかかってきた時点で、何か特定の行動を取ります(例えば、話を聞く、情報を共有するなど)。
この例ではコールバック関数は「後で呼び出される約束(関数)」です。この約束(関数)は、事前に指定された条件が満たされた時(この場合は30分経過した時)に実行されます。
敢えて非常に簡単な表現をすると、関数から呼び出される関数が「コールバック関数」だと言えるでしょう。
まずは非常にシンプルなサンプルコードから見てみましょう。
// setTimeout関数は、指定した時間が経過した後に関数(コールバック)を実行します。 // ここでは、2秒後に「Hello, Callback!」とログに表示するシンプルな例です。 setTimeout(function() { console.log('Hello, Callback!'); }, 2000); // 上記の例で、setTimeoutが親関数、渡された匿名関数がコールバック関数になります。 // 「2秒後に呼び出して」という約束をsetTimeoutにして、2秒後にコンソールにメッセージが表示されます。
↑のコード例では、setTimeout
関数(親関数)に2つの引数を渡しています。1つ目は実行されるべきコールバック関数(匿名関数で「Hello, Callback!」を表示)、2つ目はタイマーが切れるまでの時間(ミリ秒)。このとき、コールバック関数は、指定した時間(この例では2000ミリ秒、または2秒)が経過した後に自動的に呼び出されます。
基本的なコールバック関数
この章では最も基本的なコールバック関数の使用方法をご説明します。関数を別の関数に引数として渡し、内部で実行します。
function greet(callback) { console.log('Hello!'); callback(); } function smile() { console.log(':)'); } greet(smile); // 実行結果 // Hello! // :)
このサンプルコードでは2つの関数が定義されています:greet
とsmile
。
greet
関数- 引数として別の関数(コールバック関数)を受け取る。
greet
関数が呼び出されると、まず"Hello!"
をコンソールに表示し、その後に引数で受け取ったコールバック関数(この例ではsmile
関数)を実行。
- 引数として別の関数(コールバック関数)を受け取る。
smile
関数- 関数は、コンソールに
":)"
を表示する単純な関数。
- 関数は、コンソールに
コードの実行フローは↓の通り。
greet(smile);
が呼び出され、smile
関数がgreet
関数に引数として渡される。greet
関数が実行され、最初に"Hello!"
をコンソールに表示。greet
関数の内部で、引数として受け取ったsmile
関数(コールバック関数)を実行。smile
関数が実行され、コンソールに":)"
が表示される。
このサンプルコードのポイントは、ある関数(この例ではgreet
)の実行中に、引数として渡された別の関数(この例ではsmile
)を呼び出すことで、処理の流れを柔軟に制御できる点にあります。このように、コールバック関数を使うことで、特定のタイミングで任意の追加処理を挿入することが可能になります。
パラメータを伴うコールバック関数
コールバック関数にパラメータを渡す方法を示します。↓のサンプルでは、引数として関数に数値とコールバック関数を渡し、計算結果をコールバック関数を通じて処理する方法を示しています。
function calculate(x, y, callback) { const result = x + y; callback(result); } function displayResult(res) { console.log('Result: ' + res); } calculate(5, 7, displayResult); // 実行結果 // Result: 12
calculate
関数- 2つの数値(
x
とy
)とコールバック関数(callback
)を引数として受け取ります。関数内で、これら2つの数値の和を計算し、その結果をコールバック関数に渡して実行。
- 2つの数値(
displayResult
関数calculate
関数から渡された計算結果を引数として受け取り、それをコンソールに表示。
プログラムの流れは↓の通り。
calculate(5, 7, displayResult);
が呼び出される。ここで、5
と7
が加算される数値として、displayResult
がコールバック関数としてcalculate
関数に渡される。calculate
関数が実行され、x
とy
の和12
を計算。calculate
関数内で、計算結果12
をdisplayResult
関数に渡して、このコールバック関数を実行。displayResult
関数が計算結果を受け取り、"Result: 12"
としてコンソールに表示。
ポイントは、コールバック関数を利用して計算結果を処理することで、関数の処理を柔軟に拡張できる点にあります。このようにコールバック関数にパラメータを渡すことで、関数の実行後にさまざまな処理を実行することが可能になります。
非同期処理でのコールバック関数
JavaScriptの非同期処理、特にsetTimeout
を使用した非同期処理でコールバック関数を使用する例を示します。
function delayedGreeting(callback) { setTimeout(function() { console.log('Hello after 2 seconds'); callback(); }, 2000); } function smileAgain() { console.log(':) Again'); } delayedGreeting(smileAgain); // 実行結果 // Hello after 2 seconds // :) Again
このサンプルでは、JavaScriptのsetTimeout
関数の動作を模倣して、非同期処理でコールバック関数を使用する方法を示しています。
delayedGreeting
関数- 引数としてコールバック関数を受け取る。関数内では、2秒間の待機(非同期処理を模倣)が行われ、その後に
"Hello after 2 seconds"
をコンソールに表示。最後に引数で受け取ったコールバック関数を実行。
- 引数としてコールバック関数を受け取る。関数内では、2秒間の待機(非同期処理を模倣)が行われ、その後に
smileAgain
関数- コンソールに
":) Again"
を表示するシンプルな関数。
- コンソールに
コードの実行フローは↓の通り。
delayedGreeting(smileAgain);
が呼び出され、smileAgain
関数がdelayedGreeting
関数にコールバックとして渡される。delayedGreeting
関数が実行され、最初に2秒間待機。この待機期間は、非同期処理の完了を待つことを表しています。- 2秒後、
"Hello after 2 seconds"
がコンソールに表示される。 - 最後に、
delayedGreeting
関数内でsmileAgain
コールバック関数が実行され、コンソールに":) Again"
が表示されます。
このサンプルコードのポイントは、非同期処理(この例では2秒間の遅延)の完了後に特定の処理(コールバック関数)を実行する方法を示している点です。このようにコールバック関数を使用することで、非同期操作が完了した後に、自動的に追加の処理を実行することが可能になります。
複数のコールバック関数を使う
複数のコールバック関数を使って、異なる条件下で異なる処理を実行する方法を示します。これにより、より複雑なロジックを管理できます。
function fetchData(successCallback, errorCallback) { const data = { name: 'John Doe', age: 30 }; // 仮定: データの取得に成功 if (data) { successCallback(data); } else { errorCallback('No data found'); } } fetchData( function(data) { console.log('Success:', data); }, function(error) { console.log('Error:', error); } ); // 実行結果 // Success: {'name': 'John Doe', 'age': 30}
このサンプルでは、データの取得処理を模擬して成功時とエラー時に異なるコールバック関数を実行する方法を示しています。
fetchData
関数- データ取得処理。成功時のコールバック関数(
successCallback
)とエラー時のコールバック関数(errorCallback
)を引数として受け取る。関数内で、データ取得が成功したと仮定して、成功時のコールバック関数にデータを渡して実行します。データ取得が失敗した場合(この例ではシミュレートしていませんが)、エラー時のコールバック関数を実行します。
- データ取得処理。成功時のコールバック関数(
onSuccess
関数- データ取得が成功した場合に
fetchData
関数から呼び出されるコールバック関数。取得したデータをコンソールに表示します。
- データ取得が成功した場合に
onError
関数- データ取得が失敗した場合に
fetchData
関数から呼び出されるコールバック関数。エラーメッセージをコンソールに表示します。
- データ取得が失敗した場合に
コードの実行フローは以下の通り。
fetchData
関数がonSuccess
関数とonError
関数を引数として受け取りながら呼び出される。fetchData
関数内で、データの取得が成功したと仮定(data
変数に値が設定されているため)。そのため、成功時のコールバック関数onSuccess
が実行される。onSuccess
関数が取得したデータを引数として受け取り、コンソールにSuccess:
と共に表示。
このサンプルのポイントは、成功時とエラー時の処理をそれぞれ異なるコールバック関数で定義し、処理の結果に応じて適切なコールバック関数を呼び出すことで、処理の成功や失敗に柔軟に対応できる点にあります。このパターンは、非同期処理の結果に基づく複雑なフロー制御に特に有用です。
コールバック地獄
複数の非同期処理をネストして行う例を示します。このような書き方は「コールバック地獄」と呼ばれ、読みにくさや管理の難しさの原因になることを理解することが重要。
function step1(callback) { setTimeout(() => { console.log('Step 1 completed'); callback(); }, 1000); } function step2(callback) { setTimeout(() => { console.log('Step 2 completed'); callback(); }, 1000); } function step3(callback) { setTimeout(() => { console.log('Step 3 completed'); callback(); }, 1000); } step1(function() { step2(function() { step3(function() { console.log('All steps completed'); }); }); }); // 実行結果 // Step 1 completed // Step 2 completed // Step 3 completed // All steps completed
実際の開発では、プロミス(Promises)やasync/awaitなどのモダンなJavaScriptの機能を使用して、このような「コールバック地獄」を避けることが推奨されます。
コールバック関数はあまりにもネストしすぎると、人間にとって理解しづらいコードになってしまう点が注意ポイントです。
スキルアップを手軽に!
話題のサブスク型プログラミングスクールをご紹介。
SAMURAI TERAKOYA
月額2,980円から始める-入会金不要/途中解約自由。無料体験プランからスタート可能!
飲み会1回分以下の料金で継続的なスキルアップを。
Freeks(フリークス)
月額10,780円でJavaScript、Pythonなどのカリキュラムが学び放題。
質問し放題&転職サポート制度あり。
ウズウズカレッジ/CCNAコース用
月額33,000円(税込)〜インフラエンジニアの登竜門「CCNA」取得を目指す。
コース受講→転職成功で【実質全額無料】(最大240,000円)