Edited at

Switch文をObjectを使って書きかえる

More than 3 years have passed since last update.

たまにこういう感じのコードを見かけることがあります。

function processObj(obj){

var ret = {},
keys = Object.keys(obj);
for(var len = keys.length; len--;){
var key = keys[len];
var val = obj[key];
switch(key){
case "foo":
// 幾らか処理してから
// ret[key] = processed的なことする
break;
case "bar":
// ...
break;
// ...
default:
break;
}
}
return ret;
}

これでcaseが10個とか20個とかあるの見るととてもつらくなるし、こんなのをテストするのは個人的に気が進まないです。

これってswitch文をobjectとして切り分けて書けばいいんじゃないですか、と思いました。

「object vs switch statement」などで検索してみましたが、以前からこういう議論はされているようです。

function processObj(obj){

var ret = {},
keys = Object.keys(obj);
for(var len = keys.length; len--;){
var key = keys[len];
val = obj[key];
if(typeof process[key] === "function" && val != null){
ret[key] = process[key](val);
}
}
return ret;
}
var process = {
"foo": function(a){
// ...
return processed;
},
"bar": function(a){
// ...
return processed;
},
// ...
};

こうするとそれぞれのケースに対してテスト書く時に、一々objectを用意したりしないでもprocess.foo(value)とかそんな感じで値渡すだけで済むので楽な気がしませんか。

これって複数のcaseに対して1種類の処理を割り当てている時どうするの、と言われる気がするのですが、revealing module patternを適用するなりproc.foo = proc.bar = function(a){/* doSomething */}とか書けば対応できます。後者は可読性に難ありなように思いますが。

ところでパフォーマンスに差はあるのだろうかと調べてみたのですが、switch文って速いんですね。

Switch vs Hash vs Others

[追記]

コメントにて指摘を頂きましたが、object側は各ケースの処理に対し関数呼び出しが発生する為にstatementに対して遅くなるのでした。