Ne:Code道場~JavaScript コールバック関数の巻~



Ne:Code道場~JavaScript コールバック関数の巻~

プログラミング学習で、漫画など視覚的なものと併用すると楽しく継続的に学んでゆける人も多いと思います。そこでこの連載では、猫の漫画を交えつつ、JavaScriptのコールバック関数の学習ポイントについて紹介します。

目次
  1. はじめに
  2. コールバック関数って何ニャ?
  3. コールバック関数のサンプルコードを教えてニャ
  4. コールバックで実行する関数の名前考えるのが面倒ニャ
  5. ES2015以降の書き方でどんなふうにシンプルになるか教えてニャ
  6. コールバック関数難しそうニャ・・・
  7. 最後に

はじめに

image この記事ではJavaScriptのコールバック関数について、概要について取り上げつつ、躓きポイント を補足しています。 各節ごとに、Ne:Code道場(猫de道場)の弟子猫がポイントをまとめ、最後に師匠猫がそれらを総括して3ポイントでまとめています。 それらのポイントを中心に、コールバック関数について理解を深めてゆきましょう。

コールバック関数って何ニャ?

関数について、宣言・実行の書き方、また、引数や戻り値、そしてそれらを踏まえて変数のスコープを学んできました。
今回は、その延長で、コールバック関数というものを取り上げます。
例えば、関数についての最初の記事で、宣言・実行の書き方を取り上げた際に、Google Homeを用いて説明しましたが、その中で、「OK Google、○分後に教えて」という例をあげました。
実際にこの処理を実行する場合には、厳密に分解すると、

  • ○分後にタイマーをセットする処理

  • ①の時間になったらアラームを鳴らす処理

というように、大きく2つの処理で構成されているのがわかります。
これをJavaScriptで書く場合、②の処理自体を①に渡して、時間になったら②の処理を実行してもらうという記載が可能です。
肝は、処理(関数)に、処理(関数)を渡しているという点です。関数の引数として渡す関数のことを、コールバック関数といいます。
JavaScriptの関数の引数には、関数自体も渡すことができるのですね。
image

コールバック関数のサンプルコードを教えてニャ

では、1分後に「時間がきたニャ」というアラートを出すサンプルコードを取り上げます。
「○分後に特定の処理をする」部分は、JavaScriptが提供してくれる便利な機能を用います。その名も、「setTimeout」という関数です。こちらの関数には引数として、
①コールバック関数
②時間(単位ミリ秒。※1秒=1000ミリ秒)
を渡すことで、②の時間が経過した際に、①の処理を実行してくれる機能になります。
とても便利ですね。この先、JavaScript自体が提供してくれる機能を、段階をおって、記事に取り上げてゆく予定です。ぜひそれらの機能を使い倒しつつ、楽をしながらプログラミングしてゆきたいですね。
では、実際のサンプルコードを見てゆきましょう。

// 1分後に実行するコールバック関数ニャ
function showAlert() {
  alert("時間がきたニャ");  
}
 
// 1000ミリ秒で1秒になるから、1分にするために、60を掛けて、結果「60000」になっているニャ
setTimeout(showAlert, 60000);

今回、setTimeoutの引数として渡している、showAlert関数は、関数自体を渡してあげる必要があるので、関数の名前をそのまま書き、実行用の丸カッコは付いていません。
このように関数の引数には関数自体を渡すことができ、柔軟に「特定の時間の後にとある処理を一回する」機能を使ってゆくことが可能になります。
image

コールバックで実行する関数の名前考えるのが面倒ニャ

猫弟子が予定調和的な愚痴をつぶやいてくれたところで、コールバック関数と絡めて無名関数について取り上げましょう。
関数を作る際に、名前を考えることはとても重要と以前の記事でも取り上げました。
ただ、引数として関数(処理)を渡す場合は、処理自体がメインになり、あえて名前をつけようとするとどういう名前にすればよいのか考える方に時間を取られてしまう場合があります。
そんな時に輝くのが無名関数です。
無名、つまり、名無しの関数を作ることでこの問題はサクッと解消できます。
では、先程のコードを無名関数を用いる形式で修正してみます。

// functionの宣言文が跡形もなく消えているニャ!
 
// 1つ目の引数、functionの直後に丸カッコになっているニャ?!
// こっちだと行数がとても少なくなるニャ!
setTimeout(function() {
  alert("時間がきたニャ");  
}, 60000);

関数として宣言していると他の場所でも使われる可能性が出てきますが、このような無名関数としてコールバック関数として用いれば利用範囲は引数の部分だけに限定できます。
また、名前無しで作ることができるので、関数名は考えず処理のみに注力できますね。
ちなみに、このNe:Code道場では変数の宣言子としてletを用いていますが、letの利用が可能になったES2015以降では、無名関数をもう少しシンプルに書くことが可能になっています。
image

ES2015以降の書き方でどんなふうにシンプルになるか教えてニャ

まずはサンプルコードからお見せしましょう。
先程のサンプルコードをただES2015以降の書き方で記載したものになります。意味合いは同じですので、ビフォーアフターを体感いただければと思います。

// ニャ?!functionすらも消えたニャ!
// 丸カッコはそのまま残っているニャ~
// 丸カッコの後に、弓矢のような記号が続いているニャ!
setTimeout(() => {
  alert("時間がきたニャ");  
}, 60000);

イコールと不等号を組み合わせて、矢印(多少無理やり感はありますが)のような記号(=>)が書かれています。その矢印記号から、このような記載方法を「アロー関数」と呼びます。無名関数の省略記法としてES2015から利用可能になりました。
この先の記事で、JavaScriptの配列などが持っている便利機能を説明する際に、コールバック関数には、このアロー関数形式で記載してゆく予定です。その都度、書き方について補足してゆきますね。
では、ES2015について少し触れたこのタイミングで、もう一点だけ、ES2015以降で利用可能になった「テンプレート文字列」の書き方を補足します。
こちらは、先程のコードを、ユーザーが入力した分が経過した後にアラームを鳴らす形式に変更しつつ説明します。

// 「prompt」は入力用のダイアログを表示する関数ニャ
// 学習用に、値を少し変える動作を作る時に、重宝するJavaScriptの便利機能ニャ
// ダイアログに入力した数字がminutesという変数に入るニャ
let minutes = prompt("分を入力するニャ!(分以外を入力されても今回はチェックしないニャ!ちゃんと数字を入力しないとだめニャ!)");
 
// ここが、「テンプレート文字列」を利用している箇所ニャ
// 見慣れない括り文字は、ダブルコーテーションやシングルコーテーションではなく、バックコーテーションというものニャ
// バックコーテーションの内部に「${}」と書けば、そこに直接変数名を書いてOKニャ
// このようにバックコーテーションの中に埋め込み式で変数とかをそのまま書けるのが、「テンプレート文字列」だニャ
console.log(`アラームは、${minutes}分後に鳴るニャ!`);
// もちろん、下の書き方と意味は同じニャ
// 長さが短くなって、「+」で分断されないから、慣れるとテンプレート文字列の書き方は読みやすいと思うニャ
// console.log("アラームは、" + minutes+ "分後に鳴るニャ!");
 
// 入力された分をミリ秒に変換してsetTimeoutを実行しているニャ
setTimeout(() => {
  alert("時間がきたニャ");  
}, minutes * 60 * 1000);

この先のサンプルコードでは、文字列結合をする際にはこのテンプレート文字列を活用してゆく予定です。
image

コールバック関数難しそうニャ・・・

便利な機能を使う際に、使いこなすまでは学習コストがかかるというのは、実生活でも往々にしてありますね。コールバック関数はJavaScriptでそれを使わないと利用できない便利機能を活用してゆく目的で、まずは使いこなしてゆきましょう。
「自分自身で作る関数にコールバック関数を引数として渡し、処理を共通化する」等の使い道は、さらに習熟度を高めた先の話になります。
そして、JavaScriptが提供している便利な機能を利用する際のコールバック関数は、そのコールバック関数自体にも引数があるものも存在し、それを利用する際には、無名関数で書いた方がスッキリしていて、かつ、引数が何を指しているのか分かりやすいという特徴があります。
逆にそのコールバック関数を関数宣言として書いてしまうと、宣言と利用箇所が離れてしまい、その引数がどういう値になるかが判別しにくくなってしまうのです。
具体的な説明は配列等の記事に譲りますが、少しづつでもコールバック関数、およびその無名関数の記載に慣れてゆくこで、JavaScriptの便利機能を使い倒してゆきたいですね。
image

最後に

コールバック関数について、猫弟子がいくつか上げたポイントを、猫師匠が厳選3ポイントでまとめたのがこちらです。

  1. 関数の引数に、処理としての関数自体を渡す事もできるニャ
    1. 宣言した関数を渡す場合は、関数自体を渡すために、実行用の丸カッコは付けないのがポイントニャ
    2. 引数として処理自体を渡すことで柔軟なプログラミングが可能になるニャ
  2. コールバック関数には無名関数も使えるニャ
    1. 無名関数で書くことで、関数名は気にせずに処理に集中できるニャ
    2. 無名関数にしておくと、他の処理で予定外に実行されてしまう可能性もなくなるニャ
  3. JavaScriptの便利な機能を使う時にコールバック関数が必要になる場合があるニャ
    1. 提供されている便利な機能を使い倒すために、コールバック関数をしっかり抑えてゆきたいニャ

今回は、関数四回目ということで、コールバック関数を取り上げました。
関数で取り上げた引数に、まさか関数自体も渡せるとは、という可能性が膨らむコールバック関数、直近はJavaScriptの便利機能に絡めて使いこなしてゆきましょう。
便利機能を使いこなすことによって、楽で読みやすいコードを作ってゆくことができます。するとコードへの理解も深まり、プログラミングが更に楽しくなってくるでしょう。
コールバック関数の理解をしっかり身につけつつ、今後の学習に繋げてゆきましょう。
image

小泉七菜
この記事を書いた人
小泉七菜
\ 無料体験開催中!/自分のペースで確実に習得!
オンライン・プログラミングレッスンNo.1のCodeCamp