http://people.csail.mit.edu/gregs/ll1-discuss-archive-html/msg03277.html ：

closures are in fact poor man's objects (in his opinion).



...snip...



A closure is an object that supports exactly one method: "apply".

Christian Queinnecは、

closures are a poor man's objects

と言っている、一方、Norman Adamsは、

objects are a poor man's closures

と言っている、と、そんなことみたいです。「クロージャはよく知らないがオブジェクトなら知ってる」という人は多そうなので、「クロージャとは、貧乏人のオブジェクトだ」って説明は分かりやすいかも、と思ったりしました。

内容：

カウンター・クラスと貧乏なカウンター・クラス 貧乏なカウンターのクロージャによる実現 貧乏人だって頑張れば…

カウンター・クラスと貧乏なカウンター・クラス

まずは、ごく普通のカウンター・クラス。TypeScriptで書いてあります。

class Counter { private init:number; private val:number; constructor(init:number = 0) { this .init = init; this .val = this .init; } up(count:number = 1) : void { this .val += count; } down(count:number = 1) : void { this .val -= count; } value() : number { return this .val; } reset() : void { this .val = this .init; } } var c = new Counter(10); c.up(); c.up(); console.log(c.value());

クラスのメソッドは1つに限るという制約があったらどうしましょうか。up()とvalue()をひとつにまとめたupval()というメソッドでしのぐことにします。

class PoorCounter { private init:number; private val:number; constructor(init:number = 0) { this .init = init; this .val = this .init; } upval(count:number = 1) : number { this .val += count; return this .val; } } var pc = new PoorCounter(10); pc.upval();pc.upval(); console.log(pc.upval(0));

reset()メソッドはなくなってしまいましたが、まー、なんとかカウンターとして使えます。

貧乏なカウンターのクロージャによる実現

貧乏なカウンター・クラス／オブジェクトと同じ機能をクロージャを使って実現してみます。TypeScriptなので、引数／戻り値／変数にすべて型が付いてますが、とりあえずは気にしないでください（無視してよい）。型注釈（コロンとそれに続く型）と引数デフォルト値を取り除けばJavaScriptコードになります。

function createCounter(initArg:number = 0) : (count?:number)=>number { var init:number; var val:number; init = initArg; val = init; function upval(count:number = 1) : number { val += count; return val; } return upval; } var cc = createCounter(10); cc();cc(); console.log(cc(0));

貧乏なカウンター・クラス／オブジェクトとの類似点と違いに注目してください。createCounter()を生成関数、生成関数の内側で定義されたupval()をメソッド関数と呼ぶことにします、ここだけの話だけど。

クラスのインスタンス変数は、クロージャの生成関数のローカル変数になっている。

クラスのコンストラクタの動作（初期化）は、クロージャの生成関数の動作になっている。

クラスのメソッドは、クロージャのメソッド関数（入れ子の関数）になっている。

newの代わりに、クロージャの生成関数を呼ぶ。

それにより、オブジェクト＝メソッド付きのデータの代わりに、クロージャ＝データ付きの関数が生成される。

クラス／オブジェクトの場合は、newによって生成されたインスタンス・データが、クラスに所属するメソッドへの参照を持っている、という感じです*1。

それに対してクロージャの場合は、メソッド関数が内部で使う非ローカル変数を自分専用に持っています。自分専用の非ローカル変数の正体は、生成関数のローカル変数です。通常、関数のローカル変数は関数の実行が終わると消え去ります。しかし、生成関数のローカル変数valはクロージャ＝メソッド関数から参照され続けているので、消すに消せずに残っているのです。

オブジェクトにおいてはインスタンスデータが主役で、そこからメソッドが参照されている。一方、クロージャでは単一のメソッド関数が主役で、そこからデータ（生き残っている生成関数のローカル変数達）が参照されているわけです。データと関数、どちらに主眼を置くかの違いだけで、本質的には同じです。

貧乏人だって頑張れば…

クロージャでは単一のメソッドしか実現できませんでした。それゆえに貧乏なオブジェクトと言われたのです。しかし、単一のメソッドをディスパッチャー（仕事の振り分け）に使えば、複数のメソッドをサポートすることもできます。

function createRichCounter(initArg:number = 0) : (name:string, ...args:any [] )=>any { var init:number; var val:number; init = initArg; val = init; function up(count:number = 1) : void { val += count; } function down(count:number = 1) : void { val -= count; } function value() : number { return val; } function reset() : void { val = init; } function dispatch(name:string, ...args:any [] ) : any { switch (name) { case 'up' : up.apply( null , args); return ; case 'down' : down.apply( null , args); return ; case 'value' : return value.apply( null , args); case 'reset' : reset.apply( null , args); return ; default : throw "Method missing: " + name; } } return dispatch; } var rcc = createRichCounter(10); rcc( 'up' );rcc( 'up' ); console.log(rcc( 'value' ));

rcc.up(2) の代わりに rcc('up', 2)、rcc.value() の代わりに rcc('value') のように書かなくてはならないので不格好です。しかしこの問題は、構文的な細工が可能なら修正できます。機能的には元のカウンター・クラス／オブジェクトとなんら遜色ありません。

クロージャさえあれば、その応用としてオブジェクトは実装できるんだから、オブジェクトよりクロージャのほうがエライんだぞ、というのが"objects are a poor man's closures"の根拠です。どっちがエライかはどうでもいいですが、相互に相手を定義できる関係にある、ということがポイントですね。