switch
**switch
** 语句会评估一个表达式,将表达式的值与一系列 case
子句匹配,并在第一个匹配值的 case
子句之后执行语句,直到遇到 break
语句。switch
语句的 default
子句将在表达式的值与任何 case
不匹配时跳转到。
试试看
语法
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 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 语言规范 # sec-switch-statement |
浏览器兼容性
BCD 表格仅在浏览器中加载