クロージャの使い道

意外にまともな説明が無いのがクロージャである。
自分も若干不安だが挑戦してみる。
クロージャと関数の違いを説明すると、少しはましになるかも。

  • 関数(メソッド)の場合
var a = 0;
function f(x, y) {
  if(a < 2) {
    return x + y;
  } else {
    return x * y;
  }
}

a = 1;
alert(f(2, 1));
alert(f(4, 3));
a = 2;
alert(f(2, 1));
alert(f(4, 3));
function closure(a) {
  var clo = {
    f: null
  };
  if(a < 2) {
    clo.f = function(x, y) { return x + y; };
  } else {
    clo.f = function(x, y) { return x * y; };
  }
  return clo;
}

var c1 = closure(1);
var c2 = closure(2);
alert(c1.f(2, 1));
alert(c1.f(4, 3));
alert(c2.f(2, 1));
alert(c2.f(4, 3));

関数の場合は、
そのまま呼ぶだけで、パラメータとなりうるのは、
引数、クラス変数、定数になる。
内部の処理は、静的である。
クロージャの場合は、
まず、初期化が行われる。
クロージャは初期化されてから、破棄されるまで(JavaScriptの場合は画面が切り換るまで?)、
内部に値を保持し続ける。
初期化のときに与えられたパラメータによって、内部の処理を動的に変えるというような、
ポリモーフィズム的なことも可能である。
上の例では、初期化で、関数f(x, y)の処理が定義され、内部に保持し続ける。
実際、2つのクロージャc1とc2はそれぞれが別々のオブジェクトである。
それぞれの関数f(x, y)に同じパラメータを与えても、結果は違う。
これを利用すると、c1とc2を敵と味方にして対戦させるゲームを作るとか、
クロージャ(オブジェクト)をもっと増やして太陽系シミュレーションを作ることもできる。
このようなことが、1つのクラスの中で、新たにクラスを定義しなくても可能になる。
一つのクラスの中でのみ使うオブジェクトを持ちたいとき、Javaのインナークラスと
同様な処理がシンプルな記述で実現できるのが、クロージャのメリットと言える。