Javascriptのコールバック関数に関して、アウトプットのため本記事を投稿します。
Javascriptにおけるコールバック関数とは「将来のある時点で実行される関数」のことを指します。
簡易的な例
下記に例を記載します。
function a(callback) {
callback();
}
function b() {
console.log("コールバック関数として呼び出されました");
}
a(b);
//実行結果
コールバック関数として呼び出されました
処理の流れを記載します。
① aという関数を宣言します。(仮引数の名称は何でも大丈夫です)
② bという関数を宣言します。
③ ②で宣言したbという関数を実引数として、①で宣言したaという関数を呼び出します。
④ aの処理が実行され、bという関数が実行されます。
⑤ bの処理が実行され、文字列が出力されます。
関数aの仮引数には、実引数である関数bが入るので、callback() と b()は同じ命令に変換されます。
このように、コールバック関数では、引数に関数を渡して任意のタイミングで呼び出すことができます。
複雑な例
次に、前章のコードよりも複雑になったコールバック関数を解説します。
function a(callbackB) {
console.log("関数aが呼び出されました");
callbackB();
}
function b(callbackC) {
console.log("コールバック関数bが呼び出されました");
callbackC();
}
function c(callback) {
console.log("コールバック関数cが呼び出されました");
callback();
}
a(function() {
b(function() {
c(function() {
console.log("全ての処理が終了しました");
});
});
});
// 実行結果
関数aが呼び出されました
コールバック関数bが呼び出されました
コールバック関数cが呼び出されました
全ての処理が終了しました
処理の流れを記載します。
① 関数a,b,cを宣言します。
② 関数aを実行します。
③ 関数aの仮引数「callbackB」に関数aの呼び出し元の実引数が渡されます。
関数aの呼び出し元の実引数は下記コードです。
function() {
b(function() {
c(function() {
console.log("全ての処理が終了しました");
});
});
})
関数bの実引数があるため分かりづらくなっていますが、関数bの呼び出し元の実引数は使用しないので、実質的な仮引数は下記のように、関数bを呼び出す無名関数になります。
function() {
b();
})
④ 「console.log("関数aが呼び出されました")」が実行されます。
⑤ ③で渡された引数(callbackB)を実行します。
先ほど説明した通り、実引数は無名関数であるため、関数bを実行する処理になります。
⑥ 関数bの仮引数「callbackC」に、関数bの実引数(関数cを呼び出す無名関数)が渡されます。
⑦ 関数bが実行され、「console.log("コールバック関数bが呼び出されました")」が実行されます。
⑧ ⑥で渡された引数(callbackC)を実行します。
⑨ 関数cの仮引数「callback」に、関数bの実引数(無名関数)が渡されます。
実引数(無名関数)は以下です。
function() {
console.log("全ての処理が終了しました")
}
⑩ 関数cが実行され、「console.log("コールバック関数cが呼び出されました")」が実行されます。
⑪ ⑨で渡された引数を実行します。
⑫ 「console.log("全ての処理が終了しました")」が実行されます。
上記の様に、関数a,b,cを順番に実行することができます。
また、関数の呼び出し元は下記の様にアロー関数でも実行することができます。
a(() =>{
b(() =>{
c(() =>{
console.log("全ての処理が終了しました");
});
});
});
アロー関数の方が、記述がシンプルになり可読性が上がります。
setTimeoutメソッドを使用した例
setTimeoutメソッドを使用した際のコールバック関数の処理に関して記述します
function a(callback) {
setTimeout(callback, 3000);
};
function b() {
console.log("コールバック関数として呼び出されました");
};
a(b);
console.log("関数呼び出し後");
// 実行結果
関数呼び出し後
コールバック関数として呼び出されました
setTimeoutはノンブロッキングメソッドであるため、関数bが呼び出されるより先に、「console.log("関数呼び出し後")」が実行されます。
コールバック関数はあくまでも関数を順番に実行しするために使用するため、ブロッキングをして同期処理を実現いるわけではないことが分かります。