1. 程式人生 > 其它 >4.13 switch-case語句

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;
}

如果在 if-else 語句中有多個連續的分支判斷,則可以將程式碼改寫為等價的 switch 語句。在兩種寫法都可以的情況下,具體選擇哪一種只是偏好問題,認為哪一種方式的可讀性更好就選擇哪一種即可。根據情況不同,有時比起 if-else 語句,switch語句的可讀性會更好(這樣說可能帶有一些主觀偏好)。至少在使用 switch 語句時,等值比較表示式可以被隱藏起來,所以與使用了等值比較的 if-else 語句相比表達上更為簡潔。需要注意的是,switch 語句所隱藏的等值比較運算是不會對資料型別進行轉換的 === 運算。如果原來的 if-else 語句中的表示式使用的是 == 運算的話,就可能會在執行上有一些細微的差別。而這樣的問題通常不容易被發現,很容易成為產生錯誤的根源。