switch

switch 语句计算 expression,将表达式的值与一系列 case 子句进行匹配,并在第一个具有匹配值的 case 子句之后执行 statements,直到遇到 break 语句。如果没有 case 与表达式的值匹配,则将跳转到 switch 语句的 default 子句。

¥The switch statement evaluates an expression, matching the expression's value against a series of case clauses, and executes statements after the first case clause with a matching value, until a break statement is encountered. The default clause of a switch statement will be jumped to if no case matches the expression's value.

Try it

语法

¥Syntax

js
switch (expression) {
  case caseExpression1:
    statements
  case caseExpression2:
    statements
  // …
  case caseExpressionN:
    statements
  default:
    statements
}
expression

其结果与每个 case 子句匹配的表达式。

case caseExpressionN Optional

用于匹配 expressioncase 子句。如果 expression 的值与任何 caseExpressionN 的值匹配,则从 case 子句之后的第一条语句开始执行,直到 switch 语句结束或第一个遇到的 break

default Optional

default 条款;如果提供,则当 expression 的值与任何 case 子句都不匹配时执行此子句。一条 switch 语句只能有一个 default 子句。

描述

¥Description

switch 语句首先计算其表达式。然后,它查找第一个 case 子句,其表达式的计算结果与输入表达式的结果相同(使用 严格平等 比较),并将控制权转移到该子句,执行该子句后面的所有语句。

¥A switch statement first evaluates its expression. It then looks for the first case clause whose expression evaluates to the same value as the result of the input expression (using the strict equality comparison) and transfers control to that clause, executing all statements following that clause.

仅在必要时才计算子句表达式 - 如果已经找到匹配项,则后续的 case 子句表达式将不会被计算,即使它们将被 fall-through 访问。

¥The clause expressions are only evaluated when necessary — if a match is already found, subsequent case clause expressions will not be evaluated, even when they will be visited by fall-through.

js
switch (undefined) {
  case console.log(1):
  case console.log(2):
}
// Only logs 1

如果未找到匹配的 case 子句,程序将查找可选的 default 子句,如果找到,则将控制权转移到该子句,执行该子句后面的语句。如果没有找到 default 子句,则程序继续执行 switch 末尾后面的语句。按照惯例,default 子句是最后一个子句,但不一定如此。一条 switch 语句只能有一个 default 子句;多个 default 子句将导致 SyntaxError

¥If no matching case clause is found, the program looks for the optional default clause, and if found, transfers control to that clause, executing statements following that clause. If no default clause is found, the program continues execution at the statement following the end of switch. By convention, the default clause is the last clause, but it does not need to be so. A switch statement may only have one default clause; multiple default clauses will result in a SyntaxError.

突破和跌倒

¥Breaking and fall-through

你可以在 switch 语句主体中使用 break 语句来提前退出,通常是在两个 case 子句之间的所有语句都已执行时。执行将在 switch 之后的第一条语句处继续。

¥You can use the break statement within a switch statement's body to break out early, often when all statements between two case clauses have been executed. Execution will continue at the first statement following switch.

如果省略 break,执行将继续到下一个 case 子句,甚至到 default 子句,无论该子句的表达式的值是否匹配。这种行为称为 "fall-through"。

¥If break is omitted, execution will proceed to the next case clause, even to the default clause, regardless of whether the value of that clause's expression matches. This behavior is called "fall-through".

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 语句并跳转到循环的下一次迭代。

¥In the appropriate context, other control-flow statements also have the effect of breaking out of the switch statement. For example, if the switch statement is contained in a function, then a return statement terminates the execution of the function body and therefore the switch statement. If the switch statement is contained in a loop, then a continue statement stops the switch statement and jumps to the next iteration of the loop.

词汇范围

¥Lexical scoping

casedefault 子句类似于 labels:它们指示控制流可能跳转到的可能位置。然而,它们本身并不创建词汇 scopes(它们也不会自动分解 - 如上所示)。例如:

¥The case and default clauses are like labels: they indicate possible places that control flow may jump to. However, they don't create lexical scopes themselves (neither do they automatically break out — as demonstrated above). For example:

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:标识符 'message' 已被声明”,因为第一个 const message = 'hello'; 与第二个 const message = 'hi'; 声明冲突,即使它们位于各自单独的 case 子句中。最终,这是因为两个 const 声明都位于 switch 主体创建的同一块作用域内。

¥This example will output the error "Uncaught SyntaxError: Identifier 'message' has already been declared", because the first const message = 'hello'; conflicts with the second const message = 'hi'; declaration, even when they're within their own separate case clauses. Ultimately, this is due to both const declarations being within the same block scope created by the switch body.

要解决此问题,每当你需要在 case 子句中使用 letconst 声明时,请将其封装在一个块中。

¥To fix this, whenever you need to use let or const declarations in a case clause, wrap it in a block.

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,没有任何错误。

¥This code will now output hello in the console as it should, without any errors.

示例

¥Examples

使用开关

¥Using switch

在以下示例中,如果 expr 的计算结果为 Bananas,则程序将该值与 case case 'Bananas' 相匹配并执行关联的语句。当遇到 break 时,程序跳出 switch,执行 switch 后面的语句。如果省略 break,则 case 'Cherries' 的语句也会被执行。

¥In the following example, if expr evaluates to Bananas, the program matches the value with case case 'Bananas' and executes the associated statement. When break is encountered, the program breaks out of switch and executes the statement following switch. If break were omitted, the statement for the case 'Cherries' would also be executed.

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 子句之间

¥Putting the default clause between two case clauses

如果没有找到匹配项,将从 default 子句开始执行,并执行之后的所有语句。

¥If no match is found, execution will start from the default clause, and execute all statements after that.

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 子句之前时,它也有效。

¥It also works when you put default before all other case clauses.

利用跌倒的优势

¥Taking advantage of fall-through

此方法利用了以下事实:如果 case 子句下面没有 break,则执行将继续到下一个 case 子句,无论 case 是否满足条件。

¥This method takes advantage of the fact that if there is no break below a case clause, execution will continue to the next case clause regardless if that case meets the criteria.

以下是单个操作顺序 case 语句的示例,其中四个不同的值执行完全相同的操作。

¥The following is an example of a single operation sequential case statement, where four different values perform exactly the same.

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 语句中。

¥The following is an example of a multiple-operation sequential case clause, where, depending on the provided integer, you can receive different output. This shows you that it will traverse in the order that you put the case clauses, and it does not have to be numerically sequential. In JavaScript, you can even mix in definitions of strings into these case statements as well.

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

此示例的输出:

¥The output from this example:

日志文本
fooNaN 或不是 123450 请从 0 到 5 中选择一个数字!
0 输出:你的名称是什么?
1 输出:你叫什么名字?
2 输出:你的名字?
3 输出:名称?
4 输出:?
5 输出:!

if...else 链的替代方案

¥An alternative to if...else chains

你可能经常发现自己正在进行一系列 if...else 比赛。

¥You may often find yourself doing a series of if...else matches.

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 构造。

¥This pattern is not doing a sequence of === comparisons, but you can still convert it to a switch construct.

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 的替代方案特别有用。

¥The switch (true) pattern as an alternative to if...else is especially useful if you want to utilize the fall-through behavior.

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

规范

Specification
ECMAScript Language Specification
# sec-switch-statement

¥Specifications

浏览器兼容性

BCD tables only load in the browser

¥Browser compatibility

也可以看看

¥See also