switch 从多个分支中选出一个
switch 是一种控制流语句,适合把一个值与几个已知选项进行比较。一串 if/else if/else 也能做同样的事,但当你连续三四次检查同一个变量时,switch 读起来更清楚。
基本结构:
从上往下读:JavaScript 先计算 day,再把它与每个 case 标签比较,然后运行匹配的代码块。default 接住所有没匹配上的情况,就像最后的 else。阅读顺序是:值 → case → 代码。
匹配到底是怎样进行的
switch 使用严格相等比较,也就是 === 运算符。没有类型转换,也没有模糊匹配。case 1: 会匹配数字 1,但不会匹配字符串 "1"。
只有第二个 case 匹配。如果你的 switch 没有按预期触发,罪魁祸首通常是来自表单输入或 URL 参数的字符串与数字不匹配。
break 负责停下执行
这是最容易让人困惑的地方。case 标签是一个跳转目标,而不是一个独立的代码块。一旦执行落到匹配的 case 上,它就会一行一行地继续运行,直接穿过下一个 case 的标签,直到遇到 break、return 或 switch 结束。
看看没有 break 时会发生什么:
匹配的是 "editor",但你仍然会得到 can edit、can view 和 logged in。这就是穿透:因为没有任何东西让它停下,执行依次落入了后面的每个 case。
加上 break,它就规矩了:
养成习惯:除非你确实想要穿透,否则每个 case 都以 break 结尾。
有意穿透,用于分组
穿透并不总是错误。省略 break 是表达“这些 case 做的是同一件事”的简洁方式:
叠在一起的空 case 标签共享它们下面的代码块。注意,return 之后不需要 break,因为函数会直接退出。switch 中的 return 会跳过后面的所有内容。
当你确实想在非空的 case 之间穿透时,留一条注释,免得下一个读代码的人把它“修好”:
default 不一定放在最后
按照惯例,default 放在最底部,大多数读者也期望在那里看到它。但严格来说,它只是另一个标签:无论放在哪里,只要没有 case 匹配,它就会匹配。如果你把 default 放在中间又没有 break,它就会穿透到下面的代码中。把它放在最后,以 break 结尾(或者不加,因为后面已经没有内容了),将来的你会感谢现在的自己。
在 case 中声明变量的作用域
所有 case 共享一个块级作用域,也就是整个 switch。在两个 case 中用 let 或 const 声明同名变量,会抛出重复声明错误:
switch (x) {
case 1:
let msg = "one";
break;
case 2:
let msg = "two"; // SyntaxError: Identifier 'msg' has already been declared
break;
}
解决办法是每个 case 一个代码块,用 { } 把它的内容包起来:
现在每个 msg 都在自己的作用域中,冲突也就消失了。只要某个 case 需要不止一两行逻辑,就值得记住这一点。
switch 与 if/else
当你要把一个值与许多固定选项比较时,switch 最能发挥作用:HTTP 状态码、Redux action 类型、命令名、类似枚举的字符串。值只在顶部出现一次,读者的目光可以像扫目录一样扫过各个 case 标签。
在以下情况中,if/else 更合适:
- 你要比较范围(
score >= 90、score >= 75)。 - 条件涉及不同的变量或布尔表达式。
- 你需要宽松相等或自定义比较(
switch永远使用===)。
对于第一种写法,一个常见的现代替代方案是对象查找:
三行代码,代替了九行的 switch。当各个 case 只是纯粹的数据映射、没有真正的逻辑时,用对象(或 Map)通常更易读。当每个 case 都要做实际的工作时,再用 switch。
下一篇:for 循环
switch 处理的是在多个选项中做一次决定。下一种控制流是重复:一遍又一遍地运行同一段代码。这正是 for 循环的用途,下一篇就来介绍。
常见问题
JavaScript 中的 switch 语句是怎样工作的?
switch 用严格相等(===)把一个值与一系列 case 标签逐一比较。找到匹配后,它会运行该 case 的代码,并一直运行下去,直到遇到 break 或代码块结束。可选的 default 子句会在没有任何 case 匹配时运行。
JavaScript switch 中的穿透是什么?
如果一个 case 没有以 break(或 return)结尾,执行就会继续落入下一个 case 的代码中,即使那个标签并不匹配。这有时可以用来把共享逻辑的 case 归为一组,但更多时候它是个 bug。除非你有意要穿透,否则每个 case 都要以 break 结尾。
JavaScript 中什么时候该用 switch 而不是 if/else?
当你要把一个值与许多固定选项比较时,用 switch,比如 HTTP 状态码、action 类型、字符串命令。当你需要范围判断、多个变量或布尔表达式时,用 if/else。记住 switch 使用严格相等,所以 case '1' 不会匹配数字 1。