switch文を使わない 代わりの方法 をJavaScriptで本気で考えてみた

ご存知のように switch文は危険がいっぱいです。

別に気を付ければいいだけだけど、使わない方がメリットはどちらかと言えば多めです。
(もちろんswitch文にもメリットはあるけど、やっぱりできれば使いたくない)

そこで JavaScript での switch文の代わりを本気で考えてみました

switch文は break; 付け忘れリスクがあって危険

なぜ switch文 を使うのが危ないのか・・・

それは単純に break; 付け忘れのリスクがあるから。
+ あとPHPとかだと厳密な型チェックでないのも問題あり。

もし break;  をつけないとエラーになるんなら、まだ救いようがあります。

でも switch文 でそういう機能がついている言語はないから、必ずヒューマンエラーが発生してしまいますね。ほおっておくと深刻なバグの温床になるかもしれなくて怖い

 

例えば危険なコードはこんな感じ

▼ break付け忘れのヤバい例

このコードだと1つめのcase文の中身が実行された後に、 break;  がついてないから 2つ目のcase分まで実行されてしまうって訳です。

つまり 1."hogehoge" のアラート => 2."fugafuga" のアラート  という意図しない結果に、、、

これは気を付けてれば起こらないけど、疲れて仕方ない時はついやってしまいがちです。

これを回避する方法を真面目に考えてみました。

代替案1.複数のif文に置き換える

1つめは複数のif文に素直に置き換える方法

可読性は落ちるけど、変なバグが残るリスクよりはましという考え方です。

▼ 先ほどの例ならこういう感じ

う~~~ん、、、、、、

まあ見ての通りあんまりスマートじゃありません。
あとネストが1段階深くなってしまうのも少し嫌な感じもします。

でももし初心者ならトリッキーなことせず、こういう素直な書き方がいいかもしれないです。

代替案2.関数オブジェクトの配列を使うやり方

お次はコレ

関数オブジェクト配列を使って switch文 を再現する方法

JavaScriptの場合、実は 関数も組み込み型 として扱われています。

▼ 関数についてMDNでの解説

関数 は、他のコードや自分自身、関数を参照する 変数 から呼ばれるコード断片です。関数が呼ばれると、引数 が関数への入力として渡され、次に関数は任意で出力を戻します。JavaScript における関数は、オブジェクト でもあります。

引用元 : https://developer.mozilla.org/ja/docs/Web/JavaScript/Guide/Functions

▼ 実は全部 Function オブジェクトだった

JavaScript におけるすべての関数は、実際には Function オブジェクトです。

引用元 : https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Function

悪名高い(?)C言語のポインタ的な仕組みかと勘違いしてた・・・
でも関数を作成した時点で Function  というオブジェクトになるみたいですね。

その利点は 値と関数を結びつけた連想配列も作れるということ

これを使えば switch文 なんて使わなくても、スマートに条件分岐できます。

 

たとえば関数の連想配列を作った switch文 の代わりの書き方は次の通り

▼ 先ほどのコードを関数配列で書いてみた

この方法だと break;  の付け忘れなんて意識しなくていいし、関数オブジェクトがあるかどうかだけに注意しておけばかなりスマートに書けますね。

複雑な処理が必要ないなら、この書き方が一番な気がする

 

ちなみに実行する関数オブジェクトには引数も渡せます。

▼ bindメソッドを使って引数を渡す例

bindメソッドの第1引数には this  にしたいオブジェクト、その後に実行関数の引数をずらずらと渡すことが可能です。あとは好きなタイミングで呼び出せばOK

ここまでのまとめ - 関数配列を使うのが一番スマート(?)

最後に今までの方法をまとめ

個人的には2番目が一番スマートだと思います、

もし他にもっとスマートな方法があれば教えてください。ではまた($・・)/~~~

Shareこの記事をシェアしよう!

Commentsこの記事についたコメント

1件のコメント
  • 名無し

    汎用性を持たせるためにあえてFunctionの連想配列の形になさったのだと思いますが、今回の例では自分なら
    const messages = {
    hoge: ‘hogehoge’,
    fuga: ‘fugafuga’,
    piyo: ‘piyopiyo’
    }
    if(messages[which] != null){
    alert(messages[which]);
    }
    こうします。
    私もFunctionの連想配列を使うと処理の共通化ができない場面でも使えて便利だと思うのですけれど、後からif文の中身を見たときに処理内容の見当がつかず、可読性が低いのがちょっと嫌なんですよね。
    ほら、
    if(funcs[which] != null){
    funcs[which]();
    }
    これだけパッと見せられても、「条件に合致する関数を呼び出しているんだなあ」くらいしか分からないと思うんです。
    何のための何をするコードなのか、全体を見ないと理解できないというか。
    if(messages[which] != null){
    alert(messages[which]);
    }
    これだと、まだ単体で見せられても「条件に合ったメッセージ文字列をアラートする処理なのね」というところまではわかるので、リーダブルじゃないかなと。
    もちろん、Functionの連想配列を採用なさった意図はよくわかります。

    4月 28, 2022 10:24 pm

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

CAPTCHA


このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください