PR

JavaScript:コールバック関数とは?3分でわかりやすく解説

JavaScript

コールバック関数とは、別の関数に引数として渡される関数のこと。この渡された関数(コールバック関数)は、外部の関数(親関数)の内部で呼び出される形で実行されます。

// 数値を受け取り、それに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" を表示

参考 JavaScript:関数の基本

とは言え、定義とコードだけを見せられても少し難しいと思いますので、このページでは簡単なサンプルコードを見ていきながら、徐々にそのイメージが湧きやすくなるようにご説明していきます。

Webエンジニア/Webデザイナーを目指す方であれば知らないと恥ずかしい超・基本知識の1つです。是非最後までご覧ください。

参考 【JavaScript入門】基本文法/基礎文法を5分で

スポンサーリンク

コールバック関数とは?

プログラミングの基本知知識の1つ。コールバック関数はその名の通り「後で呼び出すために渡される関数」だと言えます。特に非同期操作(データを取得する、時間がかかる計算をするなど)を行う際に便利なテクニックの1つで、操作が完了したらその結果に基づいて何かアクションを起こしたいような場合にコールバック関数を使用します。

これは、日常生活の例えを使ってみるとイメージしやすくなるかもしれません。

日常生活での例え 「友人に頼んで後で電話をかけ直してもらう」状況

  1. 友人への依頼(親関数): 「忙しいから、30分後にもう一度電話して」
  2. 友人が約束を守り30分後に行動(コールバック関数): 30分後に、友人はあなたに電話をかけ直します。
  3. 電話を受けた時(コールバック関数の実行): あなたは、電話がかかってきた時点で、何か特定の行動を取ります(例えば、話を聞く、情報を共有するなど)。

この例ではコールバック関数は「後で呼び出される約束(関数)」です。この約束(関数)は、事前に指定された条件が満たされた時(この場合は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つの関数が定義されています:greetsmile

  1. greet関数
    • 引数として別の関数(コールバック関数)を受け取る。greet関数が呼び出されると、まず"Hello!"をコンソールに表示し、その後に引数で受け取ったコールバック関数(この例ではsmile関数)を実行。
  2. smile関数
    • 関数は、コンソールに":)"を表示する単純な関数。

コードの実行フローは↓の通り。

  1. greet(smile);が呼び出され、smile関数がgreet関数に引数として渡される。
  2. greet関数が実行され、最初に"Hello!"をコンソールに表示。
  3. greet関数の内部で、引数として受け取ったsmile関数(コールバック関数)を実行。
  4. 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
  1. calculate関数
    • 2つの数値(xy)とコールバック関数(callback)を引数として受け取ります。関数内で、これら2つの数値の和を計算し、その結果をコールバック関数に渡して実行。
  2. displayResult関数
    • calculate関数から渡された計算結果を引数として受け取り、それをコンソールに表示。

プログラムの流れは↓の通り。

  1. calculate(5, 7, displayResult);が呼び出される。ここで、57が加算される数値として、displayResultがコールバック関数としてcalculate関数に渡される。
  2. calculate関数が実行され、xyの和12を計算。
  3. calculate関数内で、計算結果12displayResult関数に渡して、このコールバック関数を実行。
  4. 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関数の動作を模倣して、非同期処理でコールバック関数を使用する方法を示しています。

  1. delayedGreeting関数
    • 引数としてコールバック関数を受け取る。関数内では、2秒間の待機(非同期処理を模倣)が行われ、その後に"Hello after 2 seconds"をコンソールに表示。最後に引数で受け取ったコールバック関数を実行。
  2. smileAgain関数
    • コンソールに":) Again"を表示するシンプルな関数。

コードの実行フローは↓の通り。

  1. delayedGreeting(smileAgain);が呼び出され、smileAgain関数がdelayedGreeting関数にコールバックとして渡される。
  2. delayedGreeting関数が実行され、最初に2秒間待機。この待機期間は、非同期処理の完了を待つことを表しています。
  3. 2秒後、"Hello after 2 seconds"がコンソールに表示される。
  4. 最後に、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}

このサンプルでは、データの取得処理を模擬して成功時とエラー時に異なるコールバック関数を実行する方法を示しています。

  1. fetchData関数
    • データ取得処理。成功時のコールバック関数(successCallback)とエラー時のコールバック関数(errorCallback)を引数として受け取る。関数内で、データ取得が成功したと仮定して、成功時のコールバック関数にデータを渡して実行します。データ取得が失敗した場合(この例ではシミュレートしていませんが)、エラー時のコールバック関数を実行します。
  2. onSuccess関数
    • データ取得が成功した場合にfetchData関数から呼び出されるコールバック関数。取得したデータをコンソールに表示します。
  3. onError関数
    • データ取得が失敗した場合にfetchData関数から呼び出されるコールバック関数。エラーメッセージをコンソールに表示します。

コードの実行フローは以下の通り。

  1. fetchData関数がonSuccess関数とonError関数を引数として受け取りながら呼び出される。
  2. fetchData関数内で、データの取得が成功したと仮定(data変数に値が設定されているため)。そのため、成功時のコールバック関数onSuccessが実行される。
  3. 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の機能を使用して、このような「コールバック地獄」を避けることが推奨されます。

コールバック関数はあまりにもネストしすぎると、人間にとって理解しづらいコードになってしまう点が注意ポイントです。

まとめ Javascript:コールバック関数とは?

  • コールバック関数→他の関数に引数として渡される関数
  • ある処理が完了した後に特定の動作を実行するために使用される。
  • JavaScriptの非同期処理(例えば、Web APIの呼び出しやイベントハンドラ)でよく用いられる。
  • コールバック関数を使用することで、プログラムの流れを柔軟に制御することが可能。
  • 複数の非同期処理を順序良く実行する際にも利用されるが、「コールバック地獄」という問題を引き起こす可能性がある。
// Web APIを呼び出し、結果を取得した後にコールバック関数を実行する例
function fetchData(url, callback) {
    fetch(url) // Web APIを呼び出し
        .then(response => response.json()) // レスポンスをJSON形式で解析
        .then(data => callback(data)) // 解析したデータをコールバック関数に渡して実行
        .catch(error => console.error('Error:', error)); // エラーが発生した場合の処理
}

// データ取得が成功した時の処理を定義するコールバック関数
function handleData(data) {
    console.log('Fetched data:', data);
}

// fetchData関数を呼び出し、URLとコールバック関数を引数に渡す
fetchData('https://api.example.com/data', handleData);

スキルアップを手軽に!
話題のサブスク型プログラミングスクールをご紹介。

SAMURAI TERAKOYAblank
月額2,980円から始める-入会金不要/途中解約自由。無料体験プランからスタート可能!​
飲み会1回分以下の料金で継続的なスキルアップを。

Freeks(フリークス)
blank
月額10,780円でJavaScript、Pythonなどのカリキュラムが
学び放題
質問し放題転職サポート制度あり。

ウズウズカレッジ/CCNAコース用
月額33,000円(税込)〜インフラエンジニアの登竜門「CCNA」取得を目指す。
コース受講→転職成功で【実質全額無料】(最大240,000円)

このWebサイトは現役のエンジニアが以下3点を目的として運営しています。

  1. 勉強:一度理解した内容を忘れないように。
    → アウトプットは「最強のインプット」である! 
  2. 備忘:忘れたとしても後から見返せるように。
    → 未来の自分への「お手紙」を書いています。 
  3. 共有:〇〇ってこうだったんだ!の感動をシェアできるように。
    → あなたの知識は誰かにとっての「価値ある情報」です。 

副業ブログの始め方はこちらから

スポンサーリンク
JavaScriptWEBデザイン
シェアする
ビズドットオンラインをフォローする
blank
ビズドットオンライン
タイトルとURLをコピーしました