黄子涵

4.13 switch-case语句

switch-case 语句是一种语法结构与 if-else 有所不同的条件分支判断语句。其语法结构如下。

// switch-case 语句的语法
switch ( 语句 ) {
    case 表达式 1:
        语句
        语句
        ......
    case 表达式 2:
        语句
        语句
        ......
    case 表达式 N:
        语句
        语句
        ......
    default:
        语句
        语句
        ......
}

根据习惯,“case 表达式:”部分被称为 case 标签,而 “default:” 部分被称为 default 标签。从语法规则的角度来看,它们与 if-else 语句中子句的功能不同,起到的是跳转目标的作用。在 switch 语句中可以书写多个 case 标签,而 default 标签则只能使用 1 次。此外,default 标签是可以省略的。

尽管 JavaScript 中的 switch 语句在语法结构上与 Java 的相同,但它们在实际的语法规则上却有着一些细微的差异。在 JavaScript 中,switch 的括号内可以写任意类型的表达式,case 标签中也可以写任意的表达式。与之相对应地,在 Java 的 case 标签中,则只能使用在编译时就能够获得结果的常量表达
式。

switch 语句会把其在 switch 之后的括号内的表达式,与 case 标签中所写的各个表达式,依次通过相等运算符(===)进行比较。为了避免用词混淆,这里将前者称为 switch 表达式,而将后者称为 case 表达式。=== 运算符是不会进行数据类型转换的相等运算符。switch 语句首先对 switch 表达式进行求值,之后依次对 case 表达式从上往下求值,并将其结果与 switch 表达式的求值结果进行等值比较(===)。如果值相等,则跳转至该 case 标签处。如果与所有的 case 表达式都不等值,则跳转至 default 标签处。

下面的例子主要展示了一些在 Java 中不被允许的类型。

代码清单 4.1 switch语句的例子

var hzh = '黄子涵';

switch (hzh) { // 可以在switch表达式中使用字符串值
    // 可以在case表达式中使用和switch表达式类型不同的值
    // hzh === 0 的值,所以将继续进行比较
    case 0:
        console.log("不在这里");
        break;

    // 可以在case表达式中使用含有变量的表达式
    // hzh === hzh.length 的值为假,所以继续进行比较
    case hzh.length: 
        console.log("不在这里");
        break;
        
    // 可以在 case 表达式中使用方法调用表达式
    // s === (0).toString()的值为假,所以将继续进行比较
    case (0).toString():
        console.log("不在这里");

    // 还可以在case表达式中书写这样的表达式
    // hzh === '黄' + '子' + '涵'为真,所以执行以下的代码
    case '黄' + '子' + '涵':
        console.log('在这里');
        break;
    
    // 如果所有的case表达式在等值运算(===)后得到的结果都为假,则执行以下的代码
    default: 
        console.log('不在这里');
        break;
}
[Running] node "e:\HMV\Babel\hzh.js"
在这里

[Done] exited with code=0 in 1.498 seconds

一看,case 标签之间的部分是作为一个整体来执行的,不过实际上,case 标签并没有对代码按块进行分割的功能。因此在一个 case 标签结束执行之后,并不会跳出 switch 语句。

在代码清单 4.2 的 switch 语句中,虽然第一个 case 标签的比较结果就为真,但之后所有的 case 标签也都会被执行。

代码清单 4.2 没有 break 语句的 switch 语句,将不会在执行完其中某一段 case 之后就结束整个 switch 语句

var hzh = 0;
switch (hzh) {
    case 0:
        console.log('黄子涵是帅哥!');
    case 1:
        console.log('黄子涵是靓仔!');
    case 2:
        console.log('黄子涵真聪明!');
    case 3:
        console.log('黄子涵真厉害!');
    default:
        console.log('黄子涵');
        break;
}
[Running] node "e:\HMV\JavaScript\JavaScript.js"
黄子涵是帅哥!
黄子涵是靓仔!
黄子涵真聪明!
黄子涵真厉害!
黄子涵

[Done] exited with code=0 in 2.271 seconds

由这一结果可知,应该将 case 标签与 default 标签看作跳转的目标地址。也就是应该这样来理解 case 标签的作用:当 switch 表达式与 case 表达式的值相一致时,就跳至该 case 标签所在位置,执行完该段代码之后继续从上往下逐次执行后续语句。

在很多时候,上面这样的代码都无法得到预期的结果。像代码清单 4.3 这样使用 break 语句就可以强制跳出当前 switch 语句。

代码清单 4.3 通过 break 语句跳出 switch 语句

var hzh = Math.round(Math.random()*10);
switch (hzh) {
    case 0:
        console.log('黄子涵是帅哥!');
        break;
    case 1:
        console.log('黄子涵是靓仔!');
        break;
    case 2:
        console.log('黄子涵真聪明!');
        break;
    case 3:
        console.log('黄子涵真厉害!');
        break;
    case 4:
        console.log('我是你爹!');
        break;
    case 5: 
        console.log('我是你妈!');
        break;
    case 6: 
        console.log('我是你爷!');
        break;
    case 7:
        console.log('黄子涵比彭于晏帅!');
        break;
    case 8:
        console.log('黄子涵比尤雨溪聪明!');    
        break;
    default:
        console.log('黄子涵');
        break;
}

image

如果在 if-else 语句中有多个连续的分支判断,则可以将代码改写为等价的 switch 语句。在两种写法都可以的情况下,具体选择哪一种只是偏好问题,认为哪一种方式的可读性更好就选择哪一种即可。根据情况不同,有时比起 if-else 语句,switch语句的可读性会更好(这样说可能带有一些主观偏好)。至少在使用 switch 语句时,等值比较表达式可以被隐藏起来,所以与使用了等值比较的 if-else 语句相比表达上更为简洁。需要注意的是,switch 语句所隐藏的等值比较运算是不会对数据类型进行转换的 === 运算。如果原来的 if-else 语句中的表达式使用的是 == 运算的话,就可能会在执行上有一些细微的差别。而这样的问题通常不容易被发现,很容易成为产生错误的根源。

posted @ 2022-05-27 18:05  黄子涵  阅读(346)  评论(0编辑  收藏  举报