switch
switch 語句對一個表示式進行求值,將其值與一系列 case 子句進行匹配,並執行第一個匹配的 case 子句之後的語句,直到遇到 break 語句。如果沒有任何 case 與表示式的值匹配,則會跳轉到 switch 語句的 default 子句。
試一試
const expr = "Papayas";
switch (expr) {
case "Oranges":
console.log("Oranges are $0.59 a pound.");
break;
case "Mangoes":
case "Papayas":
console.log("Mangoes and papayas are $2.79 a pound.");
// Expected output: "Mangoes and papayas are $2.79 a pound."
break;
default:
console.log(`Sorry, we are out of ${expr}.`);
}
語法
switch (expression) {
case caseExpression1:
statements
case caseExpression2:
statements
// …
case caseExpressionN:
statements
default:
statements
}
表示式-
一個表示式,其結果將與每個
case子句進行匹配。 caseExpressionN可選-
用於與
expression匹配的case子句。如果expression的值與任何caseExpressionN的值匹配,則執行從該case子句後的第一條語句開始,直到switch語句的末尾或遇到第一個break語句。 default可選-
一個
default子句;如果提供了此子句,則當expression的值不匹配任何case子句時,將執行此子句。一個switch語句只能有一個default子句。
描述
一個 switch 語句首先對它的表示式求值。然後,它查詢第一個其表示式求值結果與輸入表示式結果值相同的 case 子句(使用嚴格相等比較),並將控制權轉移到該子句,執行該子句之後的所有語句。
只有在必要時才會對子句表示式進行求值——如果已經找到匹配項,即使後續的 case 子句表示式會因穿透而被訪問,也不會對其進行求值。
switch (undefined) {
case console.log(1):
case console.log(2):
}
// Only logs 1
如果沒有找到匹配的 case 子句,程式會查詢可選的 default 子句,如果找到,則將控制權轉移到該子句,執行該子句之後的語句。如果沒有找到 default 子句,程式將繼續執行 switch 語句結束後的語句。按照慣例,default 子句是最後一個子句,但它不一定是最後一個。一個 switch 語句只能有一個 default 子句;多個 default 子句將導致 SyntaxError。
中斷和穿透
你可以在 switch 語句主體內使用 break 語句來提前跳出,通常是在兩個 case 子句之間的所有語句都已執行完畢時。執行將繼續在 switch 語句後的第一條語句。
如果省略 break,執行將繼續到下一個 case 子句,甚至是 default 子句,無論該子句的表示式值是否匹配。這種行為稱為“穿透”。
const foo = 0;
switch (foo) {
case -1:
console.log("negative 1");
break;
case 0: // Value of foo matches this criteria; execution starts from here
console.log(0);
// Forgotten break! Execution falls through
case 1: // no break statement in 'case 0:' so this case will run as well
console.log(1);
break; // Break encountered; will not continue into 'case 2:'
case 2:
console.log(2);
break;
default:
console.log("default");
}
// Logs 0 and 1
在適當的上下文中,其他控制流語句也具有跳出 switch 語句的效果。例如,如果 switch 語句包含在函式中,那麼 return 語句會終止函式主體的執行,從而終止 switch 語句。如果 switch 語句包含在迴圈中,那麼 continue 語句會停止 switch 語句並跳轉到迴圈的下一次迭代。
詞法作用域
case 和 default 子句就像標籤一樣:它們指示控制流可能跳轉到的位置。然而,它們本身並不建立詞法作用域(它們也不會自動跳出——如上所示)。例如:
const action = "say_hello";
switch (action) {
case "say_hello":
const message = "hello";
console.log(message);
break;
case "say_hi":
const message = "hi";
console.log(message);
break;
default:
console.log("Empty action received.");
}
此示例將輸出錯誤“Uncaught SyntaxError: Identifier 'message' has already been declared”,因為第一個 const message = 'hello'; 與第二個 const message = 'hi'; 宣告衝突,即使它們位於各自獨立的 case 子句中。最終,這是由於這兩個 const 宣告都位於由 switch 主體建立的同一塊作用域內。
為了解決這個問題,每當你在 case 子句中需要使用 let 或 const 宣告時,將其包裝在一個塊中。
const action = "say_hello";
switch (action) {
case "say_hello": {
const message = "hello";
console.log(message);
break;
}
case "say_hi": {
const message = "hi";
console.log(message);
break;
}
default: {
console.log("Empty action received.");
}
}
這段程式碼現在將像預期一樣在控制檯中輸出 hello,沒有任何錯誤。
示例
使用 switch
在以下示例中,如果 expr 求值為 Bananas,程式將該值與 case 'Bananas' 匹配並執行關聯的語句。當遇到 break 時,程式跳出 switch 並執行 switch 之後的語句。如果省略 break,則 case 'Cherries' 的語句也將被執行。
switch (expr) {
case "Oranges":
console.log("Oranges are $0.59 a pound.");
break;
case "Apples":
console.log("Apples are $0.32 a pound.");
break;
case "Bananas":
console.log("Bananas are $0.48 a pound.");
break;
case "Cherries":
console.log("Cherries are $3.00 a pound.");
break;
case "Mangoes":
case "Papayas":
console.log("Mangoes and papayas are $2.79 a pound.");
break;
default:
console.log(`Sorry, we are out of ${expr}.`);
}
console.log("Is there anything else you'd like?");
將 default 子句放在兩個 case 子句之間
如果沒有找到匹配項,執行將從 default 子句開始,並執行之後的所有語句。
const foo = 5;
switch (foo) {
case 2:
console.log(2);
break; // it encounters this break so will not continue into 'default:'
default:
console.log("default");
// fall-through
case 1:
console.log("1");
}
當你將 default 放在所有其他 case 子句之前時,它也適用。
利用穿透
此方法利用了這樣一個事實:如果 case 子句下方沒有 break,執行將繼續到下一個 case 子句,無論該 case 是否符合條件。
以下是一個單操作順序 case 語句的示例,其中四個不同的值執行完全相同的操作。
const Animal = "Giraffe";
switch (Animal) {
case "Cow":
case "Giraffe":
case "Dog":
case "Pig":
console.log("This animal is not extinct.");
break;
case "Dinosaur":
default:
console.log("This animal is extinct.");
}
以下是多操作順序 case 子句的示例,根據提供的整數,你可以收到不同的輸出。這表明它將按照你放置 case 子句的順序遍歷,並且不必是數字順序。在 JavaScript 中,你甚至可以在這些 case 語句中混合字串定義。
const foo = 1;
let output = "Output: ";
switch (foo) {
case 0:
output += "So ";
case 1:
output += "What ";
output += "Is ";
case 2:
output += "Your ";
case 3:
output += "Name";
case 4:
output += "?";
console.log(output);
break;
case 5:
output += "!";
console.log(output);
break;
default:
console.log("Please pick a number from 0 to 5!");
}
此示例的輸出
| 值 | 日誌文字 |
|---|---|
foo 是 NaN 或不是 1、2、3、4、5 或 0 |
請選擇一個 0 到 5 之間的數字! |
0 |
輸出:你叫什麼名字? |
1 |
輸出:你叫什麼? |
2 |
輸出:名字? |
3 |
輸出:名? |
4 |
輸出:? |
5 |
輸出:! |
if...else 鏈的替代方案
你可能經常發現自己進行一系列的 if...else 匹配。
if ("fetch" in globalThis) {
// Fetch a resource with fetch
} else if ("XMLHttpRequest" in globalThis) {
// Fetch a resource with XMLHttpRequest
} else {
// Fetch a resource with some custom AJAX logic
}
此模式不是進行一系列的 === 比較,但你仍然可以將其轉換為 switch 結構。
switch (true) {
case "fetch" in globalThis:
// Fetch a resource with fetch
break;
case "XMLHttpRequest" in globalThis:
// Fetch a resource with XMLHttpRequest
break;
default:
// Fetch a resource with some custom AJAX logic
break;
}
switch (true) 模式作為 if...else 的替代方案,在你希望利用穿透行為時特別有用。
switch (true) {
case isSquare(shape):
console.log("This shape is a square.");
// Fall-through, since a square is a rectangle as well!
case isRectangle(shape):
console.log("This shape is a rectangle.");
case isQuadrilateral(shape):
console.log("This shape is a quadrilateral.");
break;
case isCircle(shape):
console.log("This shape is a circle.");
break;
}
規範
| 規範 |
|---|
| ECMAScript® 2026 語言規範 # sec-switch-statement |
瀏覽器相容性
載入中…