switch 语句可以替代多个 if 判断。

switch 语句为多分支选择的情况提供了一个更具描述性的方式。

语法

switch 语句有至少一个 case 代码块和一个可选的 default 代码块。

就像这样:

  1. switch(x) {
  2. case 'value1': // if (x === 'value1')
  3. ...
  4. [break]
  5. case 'value2': // if (x === 'value2')
  6. ...
  7. [break]
  8. default:
  9. ...
  10. [break]
  11. }
  • 比较 x 值与第一个 case(也就是 value1)是否严格相等,然后比较第二个 casevalue2)以此类推。
  • 如果相等,switch 语句就执行相应 case 下的代码块,直到遇到最靠近的 break 语句(或者直到 switch 语句末尾)。
  • 如果没有符合的 case,则执行 default 代码块(如果 default 存在)。

举个例子

switch 的例子(高亮的部分是执行的 case 部分):

  1. let a = 2 + 2;
  2. switch (a) {
  3. case 3:
  4. alert( 'Too small' );
  5. break;
  6. case 4:
  7. alert( 'Exactly!' );
  8. break;
  9. case 5:
  10. alert( 'Too large' );
  11. break;
  12. default:
  13. alert( "I don't know such values" );
  14. }

这里的 switch 从第一个 case 分支开始将 a 的值与 case 后的值进行比较,第一个 case 后的值为 3 匹配失败。

然后比较 4。匹配,所以从 case 4 开始执行直到遇到最近的 break

如果没有 break,程序将不经过任何检查就会继续执行下一个 case

break 的例子:

  1. let a = 2 + 2;
  2. switch (a) {
  3. case 3:
  4. alert( 'Too small' );
  5. case 4:
  6. alert( 'Exactly!' );
  7. case 5:
  8. alert( 'Too big' );
  9. default:
  10. alert( "I don't know such values" );
  11. }

在上面的例子中我们会看到连续执行的三个 alert

  1. alert( 'Exactly!' );
  2. alert( 'Too big' );
  3. alert( "I don't know such values" );

任何表达式都可以成为 switch/case 的参数

switchcase 都允许任意表达式。

比如:

  1. let a = "1";
  2. let b = 0;
  3. switch (+a) {
  4. case b + 1:
  5. alert("this runs, because +a is 1, exactly equals b+1");
  6. break;
  7. default:
  8. alert("this doesn't run");
  9. }

这里 +a 返回 1,这个值跟 caseb + 1 相比较,然后执行对应的代码。

“case” 分组

共享同一段代码的几个 case 分支可以被分为一组:

比如,如果我们想让 case 3case 5 执行同样的代码:

  1. let a = 3;
  2. switch (a) {
  3. case 4:
  4. alert('Right!');
  5. break;
  6. case 3: // (*) 下面这两个 case 被分在一组
  7. case 5:
  8. alert('Wrong!');
  9. alert("Why don't you take a math class?");
  10. break;
  11. default:
  12. alert('The result is strange. Really.');
  13. }

现在 35 都显示相同的信息。

switch/case 有通过 case 进行“分组”的能力,其实是 switch 语句没有 break 时的副作用。因为没有 breakcase 3 会从 (*) 行执行到 case 5

类型很关键

强调一下,这里的相等是严格相等。被比较的值必须是相同的类型才能进行匹配。

比如,我们来看下面的代码:

  1. let arg = prompt("Enter a value?")
  2. switch (arg) {
  3. case '0':
  4. case '1':
  5. alert( 'One or zero' );
  6. break;
  7. case '2':
  8. alert( 'Two' );
  9. break;
  10. case 3:
  11. alert( 'Never executes!' );
  12. break;
  13. default:
  14. alert( 'An unknown value' )
  15. }
  1. prompt 对话框输入 01,第一个 alert 弹出。
  2. 输入 2,第二个 alert 弹出。
  3. 但是输入 3,因为 prompt 的结果是字符串类型的 "3",不严格相等 === 于数字类型的 3,所以 case 3 不会执行!因此 case 3 部分是一段无效代码。所以会执行 default 分支。

任务

将 “switch” 结构重写为 “if” 结构

重要程度: 5

将下面 switch 结构的代码写成 if..else 结构:

  1. switch (browser) {
  2. case 'Edge':
  3. alert( "You've got the Edge!" );
  4. break;
  5. case 'Chrome':
  6. case 'Firefox':
  7. case 'Safari':
  8. case 'Opera':
  9. alert( 'Okay we support these browsers too' );
  10. break;
  11. default:
  12. alert( 'We hope that this page looks ok!' );
  13. }

解决方案

为了精确实现 switch 的功能,if 必须使用严格相等 '==='

对于给定的字符串,一个简单的 '==' 也可以。

  1. if(browser == 'Edge') {
  2. alert("You've got the Edge!");
  3. } else if (browser == 'Chrome'
  4. || browser == 'Firefox'
  5. || browser == 'Safari'
  6. || browser == 'Opera') {
  7. alert( 'Okay we support these browsers too' );
  8. } else {
  9. alert( 'We hope that this page looks ok!' );
  10. }

请注意:将 browser == 'Chrome' || browser == 'Firefox' … 结构分成多行可读性更高。

switch 结构更清晰明了。

将 “if” 结构重写为 “switch” 结构

重要程度: 4

switch 重写以下代码:

  1. let a = +prompt('a?', '');
  2. if (a == 0) {
  3. alert( 0 );
  4. }
  5. if (a == 1) {
  6. alert( 1 );
  7. }
  8. if (a == 2 || a == 3) {
  9. alert( '2,3' );
  10. }

解决方案

前两个检查为前两个 case,第三个检查分为两种情况:

  1. let a = +prompt('a?', '');
  2. switch (a) {
  3. case 0:
  4. alert( 0 );
  5. break;
  6. case 1:
  7. alert( 1 );
  8. break;
  9. case 2:
  10. case 3:
  11. alert( '2,3' );
  12. break;
  13. }

请注意:最后的 break 不是必须的。但是为了让代码可扩展我们要把它加上。

有可能之后我们想要再添加一个 case,例如 case 4。如果我们忘记在它之前添加一个 break,那么在 case 3 执行结束后可能会出现错误。所以这是一种自我保险。