Hatena::ブログ(Diary)

TechTalkManiacs このページをアンテナに追加 RSSフィード

2009-11-30

JavaScriptでswitch文を使わずに条件分岐

 JavaScriptでは関数オブジェクトです。またJavaScript独自の特徴として、オブジェクトがそのままハッシュになります。なので、これを利用すると条件分岐が簡単に書けるようになります。

 これはHTML5APIやセレクトボックスで操作を切り替える場合のように、文字列で条件分岐したい。けど、Switch文のネストが複雑になりすぎる、あるいは不定数の選択肢に対して処理したいといった場合に便利です。

var  switching=function(key){
        var switchbox={};
        switchbox.a=function(){
          alert("a");
        }; 
        switchbox.b=function(){
            alert("b");
        };
        var func=switchbox[key];
        func();   
}

switching("a");//a
switching("b");//b

もちろん、外部から依存性を注入することも出来ます。

var switching(key,switchbox){
       
	var func=switchbox[key];
        func();   
};
var switchbox={};
switchbox.a=function(){
        alert("a");
}; 
switchbox.b=function(){
	alert("b");
};
switching("a",switchbox);//a
switching("b",switchbox);//b

switchbox.a=function(){
	alert("a->b");
}; 
swiwtchbox.b=function(){
		alert("b->a");
};
switching("a",switchbox);//a->b
switching("b",switchbox);//b->a

 ただし、分岐関数中でthisを使うような場合は注意が必要です


//×
var switching=function(key,switchbox){
	var func=switchbox[key];
        func();   
};
var switchbox=function(){};
switchbox.prototype.a=function(){
	alert(this.var_a);
}; 
switchbox.prototype.b=function(){
	alert(this.var_b);
};
switchbox.prototype.var_a=a; 
switchbox.prototype.var_b=b;
var box=new switchbox();
switching("a",box);//0
switching("b",box);//0

//○
var switching=function(key,switchbox){
       
	var func=switchbox[key];
        func.apply(switchbox);   
};

switching("a",box);//a
switching("b",box);//b

 javaScriptにおいてはthisは一定しません。obj.methodという静的な呼び方では他の言語と同じなのですが、今回のようにメンバ関数のみを動的に切り離して呼ぶ場合は異なってきます。詳しくはこちら

 なので、thisの動作を固定したい場合にはapplyまたはcallを使います。 applyとcallは関数オブジェクトのメソッドで、サンプルコードのように関数オブジェクトのメソッドとして呼び出します。

 一番最初の引数に内部ではthisとなる変数を指定します。例では省略していますが、applyの場合は二番目の引数関数に与えたい引数をリストとして、callの場合は通常の場合と同じように並べて与えます。

 また、クロージャを利用するとこんなことも出来ます。

var switching=function(key){
    var test="c";
    var switchbox={};
    switchbox.a=function(){
         test="a";
    }; 
    switchbox.b=function(){
         test="b";
    };
    if(key!==undefined && key in switchbox){
         var func=switchbox[key];
         func();
    }
    alert(test);

};
switching();//c
switching("a");//a
switching("b");//b
switching("c");//c

 

 処理のネストが深い時にはクロージャを閉ざされたグローバル変数のように使い、フロントコントローラーとするとこれがなかなか。

 抽象化して汎用性を上げるのって、本当に楽しいですねぇ。

(追記)サンプルのバグとインデント修正しました

mashazomashazo 2009/11/30 13:06 こんにちわ
JavaScriptはよくも悪くもできることが多いので楽しいですね

この記事の方法はちょっとびっくりしました。可能だということは知っていたのですが、そのまま条件分岐に使うというアイデアはなかったです。
ただ名称として使えない文字(/とか)だと定義時点でエラーになりそうですが、それは判定以前に入力を防ぐ?ということでしょうか

kagigotonetkagigotonet 2009/11/30 19:31  ありがとうこざいます。

 ご指摘のケースですが、オブジェクトはハッシュですので

 switchbox["/"]=function(){/*処理を書く*/}
 
という定義方法が可能ですね。

mashazomashazo 2009/12/01 18:31 こんにちわ

なるほど、文字列として渡してしまうのですね

クロージャとして実装するとしたら私の場合、以下のようにしますね。使うたびに実装を書く手間を省ける、けど、なんだかswitch文みたいになってしまった

var switching = function(def){
return function(key){
if(def && def[key]) def[key](key);
};
}

var test1 = switching(
{
"東京":
function(key){
alert("おっしゃる");
},
"大阪":
function(key){
alert("いいはる");
},
"京都":
function(key){
alert("いわはる");
}
});

var test2 = switching(
{
"源氏物語":
function(key){
alert("紫式部");
},
"枕草子":
function(key){
alert("清少納言");
},
"土佐日記":
function(key){
alert("紀貫之");
}
});

test1("東京");
test2("源氏物語");

kagigotonetkagigotonet 2009/12/08 12:56  レス遅くてすみません。
 なるほど、継承と似たメカニズムのために使う、というのは面白いですね

 クロージャには色々と使い道がありますね。

スパム対策のためのダミーです。もし見えても何も入力しないでください
ゲスト


画像認証

トラックバック - http://d.hatena.ne.jp/kagigotonet/20091130/1259547474