目的
JavaScriptのソースコードを読んでいると必ずと言っていいほど目にするコールバック関数。
処理の流れを追うのに慣れていないと混乱し(少なくとも私は)、何をしているか分からなくなります。
今回は簡単なサンプルを例に処理の流れが分かるようになることを目的に記載します。
コールバック関数とは
とある関数を呼び出す際、引数として渡される別の関数のことです。
そもそもJavaScriptでの関数とは「第一級関数」という扱いであり、簡単に説明すると「第一級関数」とは、単なる値として扱われます。
ということは、関数の引数に「値」として渡すことが可能となります。
余談ですが、関数は単なる値なので変数に代入することも可能です。
<変数に関数を代入して実行する例>
// 変数testFuncに引数ありの関数を代入 let testFunc = function(value) { console.log(value); } // 引数を渡せば実行可能 testFunc("関数実行!");
引数なしでコールバック関数を書く
サンプルコードをもとに処理の流れを確認します。
<サンプルコード>
// ①呼び出される側の関数。引数なしの関数を受け取り実行する function testFunction(testFunc) { testFunc(); } // ②呼び出す側の関数。testFunction()に関数を渡す testFunction(function() { console.log("Hello!引数なし!"); });
<処理結果>
=================== Hello!引数なし! ===================
<処理流れ>
I. ①の呼び出される側の関数の引数「testFunc」に②の呼び出す側の関数から
「function(){~}」を引数として渡します(渡す関数は特に名前を付ける必要はないです。functionでOK)。
※下記のように引数に関数が代入されるイメージ
testFunc = function() { console.log(); }
II. 「コールバック関数とは」で説明した、「変数に関数を代入して実行する例」のように
①の呼び出される側の関数の引数「testFunc」が関数として実行可能になる。
※下記のように関数として実行できるイメージ
testFunc() { console.log(); }
上記Ⅰ、Ⅱより①のtestFunction関数内で、「testFunc();」として呼び出し可能となる。
引数ありでコールバック関数を書く
サンプルコードをもとに処理の流れを確認します。
処理の流れとしては「引数なしでコールバック関数を書く」と同じです。
※コールバック関数を実行するときに引数を指定するので、通常の引数がある関数の呼び出し方と同じです。
<サンプルコード>
//①呼び出される側の関数。引数ありの関数を受け取り実行する function testFunction(testFunc) { testFunc("Hello!引数あり!"); } // ②呼び出す側の関数。testFunction()に引数ありの関数を渡す testFunction(function(value) { console.log(value); });
<処理結果>
======================= Hello!引数あり! =======================
コールバック関数の使用例
コールバック関数を利用することで非同期として実行したい処理や非同期処理後の後処理の内容を柔軟に変更可能となります。
※setTimeout()を利用した非同期処理でコールバック関数をよく見ます。
<サンプルコード>
// 本処理(本処理内で非同期処理も実行) function testExecute(callback1, callback2) { console.log("本処理"); setTimeout(function() { // 非同期として実行させたい処理 callback1(); // 非同期処理後に実行させたい処理 callback2(); }); } // 非同期として実行させたい処理1(アラート出力) function doLogic1() { alert("非同期処理(アラート処理)"); } // 非同期として実行させたい処理2(ログ出力処理) function doLogic2() { console.log("非同期処理(ログ出力処理)"); } // 非同期処理後に実行させたい後処理1(アラート出力) function afterLogic1() { alert("後処理(アラート処理)"); } // 非同期処理後に実行させたい後処理2(ログ出力処理) function afterLogic2() { console.log("後処理(ログ出力処理)"); } // 関数を引数としてtestExecute()に渡す(コールバック関数) testExecute(doLogic1, afterLogic1); testExecute(doLogic2, afterLogic2);
今回は分かりやすくするためにコールバック関数として渡す関数は
「アラート出力」と「ログ出力」となっていますが、
呼び出される側「testExecute()」の処理内容を変更せず、
渡す関数を変えるだけで処理内容を柔軟に変更できるということが分かると思います。
まとめ
コールバック関数はJavaScriptのコードを読んでいると、よく目にすると思います。
まずはサンプルプログラムのように小さいプログラムにてデバッグを利用し、
処理の流れを追いながら少しずつ理解していけばいいと思います。