クロージャを使ったフラグの切り替えサンプル
現在、自分は社内WEBシステムの スケジュール機能を作ってます。
それで スケジュールが 縦表示 横表示があって それの切り替えボタンを作ったときの 一部を紹介します
JavaScriptで、クロージャというものがあって グローバルオブジェクト汚さないように素人ながら考えて作りました。
では、ソースをどうぞ。
<!DOCTYPE html> <HTML lang="ja"> <HEAD> <meta charset="UTF-8"> <title>クロージャを使ったフラグの切り替え</title> <script type="text/javascript"> var changeArea1 = function (){ var flg = 1; return function(){ if(flg === 1){ document.getElementById( "area1" ).style.display = 'none'; document.getElementById( "area2" ).style.display = 'block'; flg = 2; } else if(flg === 2){ document.getElementById( "area1" ).style.display = 'block'; document.getElementById( "area2" ).style.display = 'none'; flg = 1; } } }(); var changeArea2 = function (){ var flg = 1; return function(){ if(flg === 1){ document.getElementById( "area3" ).style.display = 'none'; document.getElementById( "area4" ).style.display = 'block'; flg = 2; } else if(flg === 2){ document.getElementById( "area3" ).style.display = 'block'; document.getElementById( "area4" ).style.display = 'none'; flg = 1; } } }(); </script> </HEAD> <BODY> <h1>クロージャを使ったフラグの切り替え</h1><br> <button onclick="changeArea1();">area1 と area2きりかえ</button> <div id="area1"> <font color="red">area1だよーーー</font> </div> <div id="area2" style="display: none;"> <font color="blue">area2だよーーー</font> </div> <button onclick="changeArea2();">area3 と area4きりかえ</button> <div id="area3"> <font color="red">area3だよーーー</font> </div> <div id="area4" style="display: none;"> <font color="blue">area4だよーーー</font> </div> </BODY> </HTML>
area1 area2というDivボックスがありますが それをボタンを押すことで表示を切り替えるサンプルです。
area3 area4もありますがほぼ同じ処理で動いています。
このサンプルで自分が注目してほしいのは
どちらも フラグの変数名で flg という同じ変数名を使っている点です。
Javaに慣れていると {} で囲むとブロックスコープになって {}を抜けると変数が破棄されるものと考えちゃうんですが。
JavaScriptにはそもそもブロックスコープに対応していないんですよね。
なので
function changeArea1(){ var flg = 1; } function changeArea2(){ var flg = 2; }
この二つの関数は、window.flg というプロパティを共有していることになります。
では、どのようにしたらJavaのようにローカル関数みたいに使えるのでしょう?
JavaScriptでは、関数内での定義は、関数スコープになります。
つまり、関数内の定義は、関数内のみで有効になるということです。
changeArea1()について説明してみます。
var changeArea1 = function (){ var flg = 1; return function(){ if(flg === 1){ document.getElementById( "area1" ).style.display = 'none'; document.getElementById( "area2" ).style.display = 'block'; flg = 2; } else if(flg === 2){ document.getElementById( "area1" ).style.display = 'block'; document.getElementById( "area2" ).style.display = 'none'; flg = 1; } } }();
少しずつ分解します。
var changeArea1 = function(){ return 1; }(); console.log(changeArea1); //=> 1
無名関数を宣言後、すぐに実行する。 なのでchangeArea1には 1が代入される。
次は
var flg = 1; return function(){ if(flg === 1){ document.getElementById( "area1" ).style.display = 'none'; document.getElementById( "area2" ).style.display = 'block'; flg = 2; } else if(flg === 2){ document.getElementById( "area1" ).style.display = 'block'; document.getElementById( "area2" ).style.display = 'none'; flg = 1; } }
この部分ですが、無名関数内で定義するので flg変数は 無名関数内のみで有効です。
そのなかで flg変数を使った 関数を返す。 これでクロージャの完成。
var changeArea1 = function(){ if(flg === 1){ document.getElementById( "area1" ).style.display = 'none'; document.getElementById( "area2" ).style.display = 'block'; flg = 2; } else if(flg === 2){ document.getElementById( "area1" ).style.display = 'block'; document.getElementById( "area2" ).style.display = 'none'; flg = 1; } }
と同じことですが flgはこの関数内のみで有効になります。