どうもかわうそです!
今日はJavaScriptやjQueryを学んでいるとよく出てくる『callback関数』の簡単なサンプルコードを書き、説明していきたいなと思っています。
- callback関数って聞いたことあるけど、よく分からない
- callback関数って?
- そもそも関数自体がよく分かっていないかも
そんな、jQueryや、JavaScriptを学び始めた方におすすめです。
※console.log()の使用方法は勉強しておいてもらえるとなおよいです!
実はかわうそも最初は『callback?なんかよく出てくるな~。呼び戻すってことは分かるけど、よく分からんな・・・』って思ってました!
一つ一つをひも解けばそんなに難しくないので、頑張って解説しますね!
かわうそが気になる人はこちらもチェックしてみてください
現在コーダー兼エンジニアとして40サイト程の自社ECサイトを運営するIT企業で働いています。未経験転職後入社8か月で社内サイトリニューアルプロジェクトのリーダーになり、そのまま役職が主任になるも、奮闘の日々です。
こんなん作ったり
youtubeやったりしてます
Contents
callback関数とは
引数として受け取った関数を実行する関数
シンプルですが、これだけです。
関数の実行順序を制御できたり、引数によって実行する関数を管理しやすかったりといったメリットがあります!
必ず例題として上がるのが
1 |
setTimeout(function() {console.log('かわうそです');}, 1000); |
このsetTimeout()関数ですね。ただ、いきなりは分かりにくいと思うので、もう少しかみ砕いた説明を今回してみようと思っています。
- 何がcallback関数なのか
- どうやって関数が呼び出されるのか
まず、そもそも理解しにくい部分が少しでも分かるように解説していきますね!
簡単なcallback関数作ってみた
どんなものがcallback関数なのか、最初にイメージができたほうが分かりやすいですよね!
ということで、最も簡単なcallback関数を作ってみますね!
1 2 3 4 5 6 7 8 9 10 |
$(function(){ function banana(a){ console.log('bananaファンクションが実行されました') a(); }; function apple(){ console.log('callback-apple'); } banana(apple); }); |
これだけです!これがcallback関数です。これでコンソール画面には、
1 |
bananaファンクションが実行されました<br> callback-apple |
この2行が出力されるはずです。
では各行解説していきたいところですが、まずはこの関数の基礎を理解していることが必須です!
長いので別記事としてまとめましたので、こちらをもう一度おさらいしてみてください。
この関数の基礎理解ができれば、callback関数の理解はグッと進みます!
自作callback関数の各行解説する
1 2 3 4 5 6 7 8 9 10 |
$(function(){ ①function banana(a){ console.log('bananaファンクションが実行されました') ②a(); }; ③function apple(){ console.log('callback-apple'); } ④banana(apple); }); |
重要なポイントは4つです!
- 関数名 bananaの引数名をaとした
- 引数=関数名=a にして、aに()をつけ、関数名aの関数を実行している。
- 関数名appleを作成
- 関数名bananaを実行、引数に関数名appleを入れた
では説明していきますね。
まず、関数bananaと関数appleを作っています。しかし、これらは当然のことながら、まだ発動しません。
なぜなら、関数名に()を付けて、実行指示をしていないからです。
では、どこで呼びだれているかというと、ここです
1 |
banana(apple); |
分解すると、まず
1 |
banana(); |
で関数bananaを実行しています。
そして、引数に関数appleを突っ込んでいます。
1 |
banana(apple) |
なので、こうなります。
関数名に()を付ければ実行されます。
関数名だけだと、実行はされないけれども、そのファンクションの情報自体!って感じですね。
つまり、apple関数の情報はbanana関数の引数=aとして、 引き渡されたんですね。
つまり
1 2 3 4 |
①function banana(a){ console.log('bananaファンクションが実行されました') ②a(); }; |
として、引き渡されたんですね。
あれ、、、
1 |
apple(); |
apple関数が実行されましたね!
あら、こうして、
関数の引数として関数が実行されるcallback関数が生まれました!
もうちょっとだけ、callback関数に踏み込む
1 |
引数として受け取った関数を実行する関数 |
これがcallback関数でした。勘の良い方は、別の方法でcallback関数を実行できることに気が付きましたね!
①関数ごと引数にぶち込めばいいじゃん!part1
さっきまでのコードです。
1 2 3 4 5 6 7 8 9 10 |
$(function(){ function banana(a){ console.log('bananaファンクションが実行されました') a(); }; function apple(){ console.log('callback-apple'); } banana(apple); }); |
実行結果が
1 2 |
bananaファンクションが実行されました callback-apple |
でしたね。
関数情報を引数にして、実行はその関数情報を受け取ったbanana内で実行させていました。
いや、そんなまどろっこしいことしなくても
1 2 3 4 5 6 7 8 9 |
$(function(){ function banana(a){ console.log('bananaファンクションが実行されました') }; function apple(){ console.log('callback-apple'); } banana(apple()); }); |
これでいけるんじゃね!?
いけます
1 |
引数として受け取った関数を実行する関数 |
関数の実行を受け取ってるので、いけます。
コンソール出力結果を確認すると、
1 2 |
callback-apple bananaファンクションが実行されました |
そう、関数appleが先に実行されているんです。
②関数ごと引数にぶち込めばいいじゃん!part2
part1では、引数に関数の実行命令をぶち込んだんでしたね!
1 2 3 4 5 6 7 8 9 |
$(function(){ function banana(a){ console.log('bananaファンクションが実行されました') }; function apple(){ console.log('callback-apple'); } banana(apple()); }); |
てことは、もう、function apple(){}そのままぶち込んでしまえばいいんじゃね!?
callback関数って
1 |
引数として受け取った関数を実行する関数 |
つまり、
いけます
1 2 3 4 5 6 7 8 9 10 |
$(function(){ function banana(a){ console.log('bananaファンクションが実行されました') }; banana( function(){ console.log('callback-apple'); } ); }); |
えーと何をしたかというと、bananaの引数に、直接ファンクションをぶち込みました。
実行結果は
1 |
bananaファンクションが実行されました |
あれ、 callback-apple が実行されていない!
それもそのはず。
1 2 3 |
function(){ console.log('callback-apple'); } |
は実行処理ではないので、関数の実行はされないですもんね。
ということは、banana内で関数の実行を命令してあげればいい。。。
つまり
1 2 3 4 5 6 7 8 9 10 11 |
$(function(){ function banana(a){ console.log('bananaファンクションが実行されました'); a(); }; banana( function(){ console.log('callback-apple'); } ); }); |
引数として受けった関数情報を実行させればいい!
これで
1 |
bananaファンクションが実行されました<br>callback-apple |
が出力できました!
③関数ごと引数にぶち込めばいいじゃん!part3
part2では、最初このコードを書きましたね。
1 2 3 4 5 6 7 8 9 10 |
$(function(){ function banana(a){ console.log('bananaファンクションが実行されました') }; banana( function(){ console.log('callback-apple'); } ); }); |
この時、このbananaの引数である
1 2 3 |
function(){ console.log('callback-apple'); } |
を
即時関数=実行処理として以下に書き換えて渡してあげればどうなるでしょう。
1 2 3 |
(function(){ console.log('callback-apple') }()); |
つまり
1 2 3 4 5 6 |
function banana(a){ console.log('bananaファンクションが実行されました') }; banana( (function(){console.log('callback-apple')}()); ); |
実行結果は
1 |
callback-apple <br>bananaファンクションが実行されました |
いけました!
④実行順序のコントロール
これまで、いろんなパターンでcallback関数の実行を実験してきました。
それは、
1 |
引数として受け取った関数を実行する関数 |
このシンプルな設計に基づいて、検証をしてたわけですが、実行結果に違いがあった点にお気づきでしょうか。
1 2 |
bananaファンクションが実行されました callback-apple |
か
1 2 |
callback-apple bananaファンクションが実行されました |
のパターンがあったと思います。
この違いは何かって言うと、
実行命令をどこで行っているか
です。
1 |
a(); |
を使用して、banana内で実行指示を出したか
もしくは
1 |
banana(apple()); |
のように、実行処理として関数を引数で渡したかの違いなんです。
実行処理として関数を渡した場合、すぐに実行されるので
1 |
callback-apple <br>bananaファンクションが実行されました |
が出力されます。
banana内のconsole.log(‘ bananaファンクションが実行されました ‘)の処理よりも先に、apple();が呼び出され、実行されているということです。
では、a();で実行した場合は何が起きているのか
例えば、一番最初のコードのこの処理の場合
1 2 3 4 5 6 7 8 9 10 11 |
$(function(){ function banana(a){ console.log('bananaファンクションが実行されました'); a(); }; function apple(){ console.log('callback-apple'); } banana(apple); }); |
console.log(‘bananaファンクションが実行されました’);
の後に
1 |
a(); |
が実行されているので、
1 2 |
bananaファンクションが実行されました callback-apple |
となるわけです。
ということは
1 2 3 4 5 6 7 8 9 10 |
$(function(){ function banana(a){ a(); console.log('bananaファンクションが実行されました'); }; function apple(){ console.log('callback-apple'); } banana(apple); }); |
a()と console.log(‘bananaファンクションが実行されました’); の
実行順序を入れ替えるとどうなるでしょうか。
結果は
1 2 |
callback-apple bananaファンクションが実行されました |
このように、実行順序を制御することができました。
これは冒頭でお伝えしたcallback関数のメリットである、
Aの処理を終えてから、Bの処理をしたい!
ここに繋がってきます。
記述としては少し長くなってしまうのですが、大切な部分から解説させてもらいました!
最後に(setTimeout()についても)
ここまで読んで頂いてありがとうございました!
今までの話を理解して頂けた皆さんであれば、冒頭で少し触れた
1 |
setTimeout(function() {console.log('かわうそです');}, 1000); |
setTimeout’関数’がなぜcallback関数か、と言われる理由がきっとわかると思います!
構成を単純化すると、
1 |
setTimeout( function(){} , 時間(ミリ秒)); |
と、第一引数に関数を、第二引数に遅延実行時間を入れて、実行させる関数だということが分かりますね!
説明を省いている部分も多分にありますので、これがマニュアルだ!と言える完成度ではないのですが、
コールバック関数って何?どういう仕組み?と疑問を持つ方の理解の助けにはなれたんじゃないかなと思っています!
ありがとうございました!