2009年07月11日

closureをお勉強(javascript編)

javascriptのクロージャーが面白そうなので、お勉強。


典型的には、クロージャはある関数全体が他の関数(以下、エンクロージャ)の内部で宣言されたときに発生し、内部の関数はエンクロージャのローカル変数(レキシカル変数)を参照する。実行時に外部の関数が実行された際、クロージャが形成される。クロージャは内部の関数のコードとエンクロージャのスコープ内の必要なすべての変数への参照からなる。

クロージャはプログラム内で環境を共有するための仕組みである。レキシカル変数はグローバルな名前空間を占有しないという点でグローバル変数とは異なっている。またオブジェクトのインスタンス変数とは、オブジェクトのインスタンスではなく関数の呼び出しに束縛されているという点で異なる。

クロージャは関数型言語では遅延評価やカプセル化のために、また高階関数の引数として広く用いられる。

というものらしい。 という事で、下にクロージャーを使ったテストプログラムを作ってみた。◆closureTest1:オーソドックスなクロージャー

<script type="text/javascript">
//オーソドックスなClosure
function generateClosure1(tag){
var tag_end = '</' + tag + '>';
function returnClosure(textnode){
return '<'+tag+'>' + textnode + tag_end;
}
return returnClosure;
}
function closureTest1()
{
var closure_h1 = generateClosure1('h1');
var closure_h2 = generateClosure1('h2');
var closure_h3 = generateClosure1('h3');

var tmp = '';
tmp += closure_h1('h1の文章') + '<br />';
tmp += closure_h2('h2の文章') + '<br />';
tmp += closure_h3('h3の文章') + '<br />';

$('#test1').html(tmp);
}
</script>
オーソドックスなクロージャー:<input type="button" onclick="closureTest1();" value="closureTest1"><br/>
<div id="test1"></div>


オーソドックスなクロージャー:



これは、想像通りの動作をしてくれると思います。オーソドックスなクロージャーっすね。
◆closureTest2:グローバル変数にアクセスするクロージャー

<script type="text/javascript">
//グローバル変数にアクセスするClosure
function generateClosure2(tag){
var tag_end = '</' + tag + '>';
function returnClosure(textnode){
return '<'+tag+'>' + textnode + ':' + g_strTest + tag_end;
}
return returnClosure;
}
function closureTest2()
{
var closure_h1 = generateClosure2('h1');
var closure_h2 = generateClosure2('h2');
var closure_h3 = generateClosure2('h3');

var tmp = '';
g_strTest = 'hoge1';
tmp += closure_h1('h1の文章') + "<br />";
g_strTest = 'hoge2';
tmp += closure_h2('h2の文章') + "<br />";
g_strTest = 'hoge3';
tmp += closure_h3('h3の文章') + "<br />";

$('#test2').html(tmp);
}
</script>
グローバル変数にアクセスするクロージャー:<input type="button" onclick="closureTest2();" value="closureTest2"><br/>
<div id="test2"></div>


グローバル変数にアクセスするクロージャー:



クロージャーの関数を実行時に、グローバル変数を参照しているので、これも想像通り。
◆closureTest3:クロージャー作成後にレキシカル変数の値を更新

<script type="text/javascript">
//クロージャー作成後にレキシカル変数の値を更新
function generateClosure3(tag){
var tag_end = '</' + tag + '>';
function returnClosure(textnode){
return '<'+tag+'>' + textnode + tag_end;
}
tag_end = 'ガッデム!!';
return returnClosure;
}
function closureTest3()
{
var closure_h1 = generateClosure3('h1');
var closure_h2 = generateClosure3('h2');
var closure_h3 = generateClosure3('h3');

var tmp = '';
tmp += closure_h1('h1の文章') + "<br />";
tmp += closure_h2('h2の文章') + "<br />";
tmp += closure_h3('h3の文章') + "<br />";

$('#test3').html(tmp);
}
</script>
クロージャー作成後にレキシカル変数の値を更新:<input type="button" onclick="closureTest3();" value="closureTest3"><br/>
<div id="test3"></div>


クロージャー作成後にレキシカル変数の値を更新:



これが、少しイメージ付き辛い気がする。 クロージャー(returnClosure)作成時にエンクロージャのローカル変数(レキシカル変数)の参照を保持するので、クロージャー作成後に、レキシカル変数の値が変更された場合、クロージャー関数実行時には変更後の値が参照される。


posted by purigen at 01:06| Comment(0) | TrackBack(0) | javascript | このブログの読者になる | 更新情報をチェックする
この記事へのコメント
コメントを書く
お名前:

メールアドレス:

ホームページアドレス:

コメント:

認証コード: [必須入力]


※画像の中の文字を半角で入力してください。

この記事へのトラックバック
×

この広告は180日以上新しい記事の投稿がないブログに表示されております。