コールバック

「この処理は、こことそこで使いまわせるよね。差分を関数で渡して埋められるよう、コールバックで実装してもらえないか?」と振ったら、「コールバック?」と固まってしまったようなのでフォローした。

そのときは、われながら教科書みたいな例を出せたんじゃないかなと自画自賛したくなって、今まとめなおしてみたのだけれど、あまりいい例ではなかった、気がしてきた。余計混乱させたんじゃなかろうか。無念。

      • -

メソッド、という言い方だとしっくりこないので「関数」と呼び変えます。
関数を呼ぶときに関数を渡し、呼び出した関数の中で渡された関数を呼び返す。これがコールバックです。

実例。

function add(a, b) { return a + b; };

これは(意味がないように見えますが)、次のように書き換えられます。

function add(a, b) {
  var plus = function(a, b) { return a + b; };
  return plus(a, b);
};

この add の中で定義した関数 plus は、関数の外から引数で渡すように書き換えられます。

function plus(a, b) { return a + b; };
function add(plus, a, b) { return plus(a, b); };

この時点での add 関数定義の意味を漂白すると、引数 a, b に(コールバックとして渡される)関数 f を適用する関数 apply が見えてきます。

function apply(f, a, b) { return f(a, b); };

apply に渡す関数 f を以下で差し替えるとどうなるでしょうか。

function sub(a, b) { return a - b; };
function mul(a, b) { return a * b; };
function div(a, b) { return a / b; };

何が言えるかのまとめ。
最初の定義 function add(a, b) { return a + b; } は (+) という計算アルゴリズムが固定されていて自由度がない。一方で、コールバック関数を渡せる apply を仲介すると各種計算アルゴリズムをあとから注入できる。(つまり設計の自由度、抽象度があがった)

なお、コールバックを使う代表的な設計手法に、テンプレートメソッドや計算アルゴリズムの差し替え(先の apply のような)があります。