switch

Baseline 已廣泛支援

此特性已相當成熟,可在許多裝置和瀏覽器版本上使用。自 ⁨2015 年 7 月⁩以來,各瀏覽器均已提供此特性。

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}.`);
}

語法

js
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 子句表示式會因穿透而被訪問,也不會對其進行求值。

js
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 子句,無論該子句的表示式值是否匹配。這種行為稱為“穿透”。

js
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 語句並跳轉到迴圈的下一次迭代。

詞法作用域

casedefault 子句就像標籤一樣:它們指示控制流可能跳轉到的位置。然而,它們本身並不建立詞法作用域(它們也不會自動跳出——如上所示)。例如:

js
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 子句中需要使用 letconst 宣告時,將其包裝在一個塊中。

js
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' 的語句也將被執行。

js
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 子句開始,並執行之後的所有語句。

js
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 語句的示例,其中四個不同的值執行完全相同的操作。

js
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 語句中混合字串定義。

js
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!");
}

此示例的輸出

日誌文字
fooNaN 或不是 123450 請選擇一個 0 到 5 之間的數字!
0 輸出:你叫什麼名字?
1 輸出:你叫什麼?
2 輸出:名字?
3 輸出:名?
4 輸出:?
5 輸出:!

if...else 鏈的替代方案

你可能經常發現自己進行一系列的 if...else 匹配。

js
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 結構。

js
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 的替代方案,在你希望利用穿透行為時特別有用。

js
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

瀏覽器相容性

另見