switch
语句可以替代多个 if
判断。
switch
语句为多分支选择的情况提供了一个更具描述性的方式。
switch
语句有至少一个 case
代码块和一个可选的 default
代码块。
就像这样:
switch(x) { case 'value1': // if (x === 'value1') ... [break] case 'value2': // if (x === 'value2') ... [break] default: ... [break] }
比较 x
值与第一个 case
(也就是 value1
)是否严格相等,然后比较第二个 case
(value2
)以此类推。
如果相等,switch
语句就执行相应 case
下的代码块,直到遇到最靠近的 break
语句(或者直到 switch
语句末尾)。
如果没有符合的 case,则执行 default
代码块(如果 default
存在)。
switch
的例子(高亮的部分是执行的 case
部分):
let a = 2 + 2; switch (a) { case 3: alert( 'Too small' ); break; case 4: alert( 'Exactly!' ); break; case 5: alert( 'Too big' ); break; default: alert( "I don't know such values" ); }
这里的 switch
从第一个 case
分支开始将 a
的值与 case
后的值进行比较,第一个 case
后的值为 3
匹配失败。
然后比较 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" ); }
在上面的例子中我们会看到连续执行的三个 alert
:
alert( 'Exactly!' ); alert( 'Too big' ); alert( "I don't know such values" );
任何表达式都可以成为 switch/case
的参数
switch
和 case
都允许任意表达式。
比如:
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"); }
这里 +a
返回 1
,这个值跟 case
中 b + 1
相比较,然后执行对应的代码。
共享同一段代码的几个 case
分支可以被分为一组:
比如,如果我们想让 case 3
和 case 5
执行同样的代码:
let a = 3; switch (a) { case 4: alert('Right!'); break; case 3: // (*) 下面这两个 case 被分在一组 case 5: alert('Wrong!'); alert("Why don't you take a math class?"); break; default: alert('The result is strange. Really.'); }
现在 3
和 5
都显示相同的信息。
switch/case
有通过 case 进行“分组”的能力,其实是 switch 语句没有 break
时的副作用。因为没有 break
,case 3
会从 (*)
行执行到 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' ) }
在 prompt
对话框输入 0
、1
,第一个 alert
弹出。
输入 2
,第二个 alert
弹出。
但是输入 3
,因为 prompt
的结果是字符串类型的 "3"
,不严格相等 ===
于数字类型的 3
,所以 case 3
不会执行!因此 case 3
部分是一段无效代码。所以会执行 default
分支。
重要程度: 5
将下面 switch
结构的代码写成 if..else
结构:
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
用 switch
重写以下代码:
let a = +prompt('a?', ''); if (a == 0) { alert( 0 ); } if (a == 1) { alert( 1 ); } if (a == 2 || a == 3) { alert( '2,3' ); }
前两个检查为前两个 case
,第三个检查分为两种情况:
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
,例如 case 4
。如果我们忘记在它之前添加一个 break,那么在 case 3 执行结束后可能会出现错误。所以这是一种自我保险。