2021年8月26日

switch文

switch 文は複数の if チェックに置換できます。

これは値を複数のパターンと比較するための、よりわかりやすい方法を提供します。

構文

switch は1つ以上の case ブロックを持ち、 オプションで default を持ちます。

このようになります:

switch(x) {
  case 'value1':  // if (x === 'value1')
    ...
    [break]

  case 'value2':  // if (x === 'value2')
    ...
    [break]

  default:
    ...
    [break]
}
  • x の値は、最初の case (それは value1)の値と厳密な等価のチェックをされます、そして2つ目(value2)と続きます。
  • 等価なものが見つかった場合、 switch は該当する case から始まるコードを実行し始めます。最も近い break まで(もしくは switch の終わりまで)。
  • マッチするケースが無い場合は、default コードが実行されます(存在する場合)

switch の例です(実行されるコードはハイライトされています)

let a = 2 + 2;

switch (a) {
  case 3:
    alert( 'Too small' );
    break;
  case 4:
    alert( 'Exactly!' );
    break;
  case 5:
    alert( 'Too large' );
    break;
  default:
    alert( "I don't know such values" );
}

ここで、 switch は、最初の case である 3 から a との比較を始めます。マッチはしません。

そして 4 です。マッチするので、case 4 から最も近い break までの実行を開始します。

break がない場合、チェックなしで次の case の実行を継続します。

break なしの例です:

let a = 2 + 2;

switch (a) {
  case 3:
    alert( 'Too small' );
  case 4:
    alert( 'Exactly!' );
  case 5:
    alert( 'Too big' );
  default:
    alert( "I don't know such values" );
}

上の例では、3つの alert が順に実行されるでしょう。

alert( 'Exactly!' );
alert( 'Too big' );
alert( "I don't know such values" );
どのような式も switch / case の引数になります

switchcase の両方は任意の表現が可能です。

例:

let a = "1";
let b = 0;

switch (+a) {
  case b + 1:
    alert("this runs, because +a is 1, exactly equals b+1");
    break;

  default:
    alert("this doesn't run");
}

ここで +a1 が与えられ、 caseb + 1 と比較されます。そして、対応するコードが実行されます。

"case"のグルーピング

同じコードを共有する複数の case のパターンはグループ化できます。

たとえば、case 3case 5 で同じコードを実行したい場合:

let a = 2 + 2;

switch (a) {
  case 4:
    alert('Right!');
    break;

  case 3:                    // (*) 2つのケースをグループ化
  case 5:
    alert('Wrong!');
    alert("Why don't you take a math class?");
    break;

  default:
    alert('The result is strange. Really.');
}

今、35 は同じメッセージを表示します。

ケースを “グループ化” する機能は、break がない場合の switch/case の動作の副作用です。ここで case 3 の実行は、break がないので (*) の行から始まり、case 5 を通り抜けます。

型の問題

等価チェックは常に厳密であることに注目しましょう。マッチするために値は同じ型である必要があります。

たとえば、このコードを考えてみましょう:

let arg = prompt("Enter a value?")
switch (arg) {
  case '0':
  case '1':
    alert( 'One or zero' );
    break;

  case '2':
    alert( 'Two' );
    break;

  case 3:
    alert( 'Never executes!' );
    break;
  default:
    alert( 'An unknown value' )
}
  1. 0, 1 の場合、最初の alert が実行されます。
  2. 2 の場合は2つ目の alert が実行されます。
  3. しかし 3 の場合、prompt の結果は文字列の "3"なので、数字の 3 との厳密な等価 === ではありません。そのため、case 3 はデッドコードです! default ケースが実行されるでしょう。

タスク

重要性: 5

if..else を使って次の switch に対応するコードを書いてください。:

switch (browser) {
  case 'Edge':
    alert( "You've got the Edge!" );
    break;

  case 'Chrome':
  case 'Firefox':
  case 'Safari':
  case 'Opera':
    alert( 'Okay we support these browsers too' );
    break;

  default:
    alert( 'We hope that this page looks ok!' );
}

switch の機能に正確にマッチさせるためには、if は厳密な比較 '===' を使わなければなりません。

が、与えられた文字列に対しては、単純な '==' も使えます。

if(browser == 'Edge') {
  alert("You've got the Edge!");
} else if (browser == 'Chrome'
 || browser == 'Firefox'
 || browser == 'Safari'
 || browser == 'Opera') {
  alert( 'Okay we support these browsers too' );
} else {
  alert( 'We hope that this page looks ok!' );
}

注意してください: 構造 browser == 'Chrome' || browser == 'Firefox' … はより良い可読性のために複数行に分割されています。

しかし、switch 構造は以前としてより洗練されており、説明的です。

重要性: 4

下のコードを1つの switch 文を使って書き換えてください。:

let a = +prompt('a?', '');

if (a == 0) {
  alert( 0 );
}
if (a == 1) {
  alert( 1 );
}

if (a == 2 || a == 3) {
  alert( '2,3' );
}

最初の2つのチェックは2つの case になります。3つ目のチェックは2つのケースに分割されます。:

let a = +prompt('a?', '');

switch (a) {
  case 0:
    alert( 0 );
    break;

  case 1:
    alert( 1 );
    break;

  case 2:
  case 3:
    alert( '2,3' );
    break;
}

注意してください: 末尾の break は必須ではありませんが、将来のためにそれを置く方がよいです。

将来、たとえば case 4 のような case を追加したい機会があります。そして、以前に break を置くのを忘れていた場合、 case 3 の終わりでエラーが発生します。なので、これは一種の自己保険です。

チュートリアルマップ