2007年11月19日月曜日

クロージャ 3

JavaScript でクロージャを考えます。
クロージャクロージャと Privileged メソッド の続きです。
この前、簡単にクロージャの考え方を示したら、クロージャは面白そうだけれども、結局どんなことができるの? と聞かれてしまいました。
まだまだ例が不足しているので、僕が前からチェックしようと思っていてなかなかチェックできていなかった、Javascript Closures
というサイトがあるのでいま一度チェックしてみました。

ここにはクロージャを使った 3 つの例が示されています。

例 1: 関数への参照を使った setTimeout

これは前に示しました。
// 無名内部関数への参照を返す
function callLater(elem, paramB, paramC){
return (function(){
elem.style[paramB] = paramC;
});
}

//
// 実行時のコンテクストによって生成された内部関数への参照を返す
// 関数を呼出す。
//
var functRef = callLater(document.getElementById('clHead')
, 'display', 'none');

//
// 0.5 秒後にエレメントを消す
//
setTimeout('functRef()', 500);

例 2: オブジェクトのインスタンスメソッドに関数を関連させる

2 つめに挙げられている例は以下のように、自分でイベント名を定義し直すパターンです。この例では定義し直しているメソッドは 1 つだけだけれども、複数定義する場合で、オブジェクトのインスタンスを沢山生成するときには便利そうです。
function associateObjWithEvent(obj, methodName){
return (function(e){
e = e||window.event;
return obj[methodName](e, this);
});
}

function DhtmlObject(elemId){
var el = document.getElementById(elemId);
// 要素が見つかったとき
if(el){
el.onclick = associateObjWithEvent(this, 'doOnClick');
}
}

DhtmlObject.prototype.doOnClick = function(event, element){
alert('要素をクリックしました。');
};

var a = new DhtmlObject('clObjI');

例3: カプセル化

最後は分かりやすいです。image 要素を持った div 要素の様々なプロパティをクロージャを使って指定する例です。様々に指定して要素が作れますね。
var getImgInPositionedDivHtml = (function(){
var buffAr = [
'<div id="',
'', //index 1, DIV ID attribute
'" style="position:absolute;top:',
'', //index 3, DIV top position
'px;left:',
'', //index 5, DIV left position
'px;width:',
'', //index 7, DIV width
'px;height:',
'', //index 9, DIV height
'px;overflow:hidden;\"><img src=\"',
'', //index 11, IMG URL
'\" width=\"',
'', //index 13, IMG width
'\" height=\"',
'', //index 15, IMG height
'\" alt=\"',
'', //index 17, IMG alt text
'\"><\/div>'
];

return (function(url, id, width, height, top, left, altText){
buffAr[1] = id;
buffAr[3] = top;
buffAr[5] = left;
buffAr[13] = (buffAr[7] = width);
buffAr[15] = (buffAr[9] = height);
buffAr[11] = url;
buffAr[17] = altText;
return buffAr.join('');
});
})();

document.getElementById('clHead').innerHTML =
getImgInPositionedDivHtml(
'http://www.cirius.co.jp/',
'new-elem',
'100',
'100',
'100',
'100',
'新しい要素'
);

そのほか


この他には クロージャと Privileged メソッド で挙げた Privileged メソッドが良い例ですね。

追記: JavaScript とクロージャ も面白いです。