クロージャ

Cには入れ子関数が無いため、クロージャの意味や使い方がさっぱりわからなかった。
匿名関数を即実行するのが気持ち悪かったということもある。

エンクロージャのローカル変数が静的に保持されていることに考えが及び、ちょっと使い方がわかった気がする。

そこで理解を深めるために書いたサンプルコード

'use strict';

// Closureサンプルコード

// カウントアップ、ダウン、
// カウンタリセット、カウンタリードが出来るユーティリティ

var CounterUtil;

if (!CounterUtil) {
	// オブジェクト生成
	CounterUtil = {};
	
	// 匿名エンクロージャ即実行
	(function () {
		var cnt = 0;	// カウンタ(クロージャ)
		
		// カウンタリセット(クロージャ)
		CounterUtil.Reset = function () {
			return (cnt = 0);
		};
		
		// カウンタインクリメント(クロージャ)
		CounterUtil.Increase = function () {
			return ++cnt;
		};
		
		// カウンタデクリメント(クロージャ)
		CounterUtil.Decrease = function () {
			return --cnt;
		};
		
		// カウンタ参照(クロージャ)
		CounterUtil.Read = function () {
			return cnt;
		};
	})();
}

console.log(CounterUtil.Read());
console.log(CounterUtil.Increase());
console.log(CounterUtil.Increase());
console.log(CounterUtil.Increase());
console.log(CounterUtil.Decrease());
console.log(CounterUtil.Reset());
console.log(CounterUtil.Decrease());

初め名前空間用オブジェクト名をCounterにしていたら、定義済みで、Read関数が未定義って怒られて、悩んだ。MDNでは見当たらないので、WebKitのオブジェクトだろうか。nativeコードになっていた。

更に改善するために

サンプルコードでは、cntは静的になっているため、カウンタはひとつしか無い。
マルチプルインスタンス化できるか考えてみよう。
インスタンスフィールドに関数オブジェクトを設定し、それがエンクロージャになれば良い?