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
switch (expression) {
case caseExpression1:
statements
case caseExpression2:
statements
// …
case caseExpressionN:
statements
default:
statements
}
expression
-
其结果与每个
case
子句匹配的表达式。 case caseExpressionN
Optional-
用于匹配
expression
的case
子句。如果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.
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".
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
case
和 default
子句类似于 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:
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
子句中使用 let
或 const
声明时,请将其封装在一个块中。
¥To fix this, whenever you need to use let
or const
declarations in a case
clause, wrap it in a block.
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.
示例
使用开关
¥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.
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.
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.
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.
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:
值 | 日志文本 |
---|---|
foo 是 NaN 或不是 1 、2 、3 、4 、5 或 0 |
请从 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.
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.
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.
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 |
浏览器兼容性
BCD tables only load in the browser
也可以看看
¥See also