首页
/ freeCodeCamp 课程精讲:用 JavaScript switch 语句替换 if/else if 链

freeCodeCamp 课程精讲:用 JavaScript switch 语句替换 if/else if 链

2026-09-07 16:54:26作者:庞队千Virginia

本篇围绕 freeCodeCamp 开源仓库中 Basic JavaScript(基础 JavaScript)课程的一节真实挑战文档展开,主题是将冗长的 if/else if 判断链改写成等价的 switch 语句。文中会完整还原该挑战的目标、起始代码、逐条验收测试与官方参考实现,并结合仓库中的挑战结构元数据与校验 Schema,说明这类"代码改写型"练习在 freeCodeCamp 课程体系里是如何组织、如何被自动判定的。

本节挑战在课程中的位置

本节挑战 Replacing If Else Chains with Switch 位于课程块 basic-javascript 内,对应源文件为 curriculum/challenges/english/blocks/basic-javascript/56533eb9ac21ba0edf2244e0.md。从它的 YAML frontmatter 可以看到:

  • id: 56533eb9ac21ba0edf2244e0:全仓库唯一的挑战 ID,被课程元数据与文件系统共同引用;
  • titledashedNamereplacing-if-else-chains-with-switch,用于 URL、文件命名与链接;
  • challengeType: 1:对照 packages/shared/src/config/challenge-types.ts 可知,类型 1js,表示这是一道面向单文件 JavaScript 代码的经典练习题;
  • forumTopicId:用于关联课程论坛的讨论帖。

每个课程的挑战顺序不是由文件名决定的,而是登记在块元数据中。在 curriculum/structure/blocks/basic-javascript.jsonchallengeOrder 数组里可以看到本节前后的完整脉络:

Golf Code
Selecting from Many Options with Switch Statements   ← switch 系列第 1 课
Adding a Default Option in Switch Statements          ← 第 2 课:default 语句
Multiple Identical Options in Switch Statements       ← 第 3 课:合并相同分支 / fall-through
Replacing If Else Chains with Switch                  ← 第 4 课(本节):if/else if → switch 改写
Returning Boolean Values from Functions

也就是说,本节是"switch 四连课"的收尾一课:前三课分别讲 switch 的基础语法、default 兜底分支、多个相同输入共享同一输出,本节则要求学习者把此前学过的 if/else if 链整体翻译成 switch,完成新旧两种分支写法的"等价互换"。

为什么多分支场景下 switch 更易读

本节文档开篇给出的判断依据非常朴素:当可选分支很多时,switch 往往比一长串 if/else if 更容易编写。链式判断存在两个天然缺陷:

  1. 噪音高:每个分支都要重复写 val === ... 这样的判断头,真正有区分度的只有那个常量值;
  2. 结构扁平度差else if 层层嵌套的书写形式,让分支边界不如 case 那样一目了然。

文档给出的对照示例:

if (val === 1) {
  answer = "a";
} else if (val === 2) {
  answer = "b";
} else {
  answer = "c";
}

可以等价替换为:

switch (val) {
  case 1:
    answer = "a";
    break;
  case 2:
    answer = "b";
    break;
  default:
    answer = "c";
}

这里能"等价替换"有一个关键前提:switch 的分支匹配使用的是严格相等(===,而原 if/else if 链的每个判断也恰恰是 val === 1 形式的严格比较,因此两者在语义上完全一致——不存在 1 == '1' 这类隐式类型转换带来的差异。这一点在同块的前序挑战文档中有明确表述,见 Selecting from Many Options with Switch Statements

另外注意映射关系:if 链末尾的 else 兜底对应的是 switchdefault 分支,而 default 在 switch 中应当放在最后一个 case 之后(这是同块另一课 Adding a Default Option in Switch Statements 的要点)。

练习目标:把 chainToSwitch 改写成 switch

本节文档的指令部分(--instructions--)要求:把函数 chainToSwitch 内部连续的 if/else if 语句改写为 switch 语句,且不得改变函数行为。

起始代码(--seed-contents--)如下:

function chainToSwitch(val) {
  let answer = "";
  // Only change code below this line

  if (val === "bob") {
    answer = "Marley";
  } else if (val === 42) {
    answer = "The Answer";
  } else if (val === 1) {
    answer = "There is no #1";
  } else if (val === 99) {
    answer = "Missed me by this much!";
  } else if (val === 7) {
    answer = "Ate Nine";
  }

  // Only change code above this line
  return answer;
}

chainToSwitch(7);

可见这是一个"值 → 输出"的查表型函数:根据参数 val 命中 5 种输入,各返回一句特定字符串;任何未列出的输入(如 "John"156)都会保持 answer 的初始值,最终返回空字符串。

改写的基本思路如下:

  1. switch (val) { ... } 包裹原函数体中的分支逻辑;
  2. 把每个 if (val === X) 变成 case X:
  3. 保留原 answer = "..."; 赋值语句;
  4. 在除最后一个分支外的每个 case 结尾补上 break;,阻止执行"穿透"(fall-through)到下一个分支;
  5. 原函数没有 else 兜底分支,因此这里也不需要 default——这正是它与上面的 if 链保持一致的要点之一。

文档末尾给出的官方参考实现(--solutions--):

function chainToSwitch(val) {
  let answer = "";

  switch (val) {
    case "bob":
      answer = "Marley";
      break;
    case 42:
      answer = "The Answer";
      break;
    case 1:
      answer = "There is no #1";
      break;
    case 99:
      answer = "Missed me by this much!";
      break;
    case 7:
      answer = "Ate Nine";
  }
  return answer;
}

注意两个容易忽略的细节:

  • case "bob"case 42 说明同一个 switch 内可以混用字符串与数值类型的匹配常量,类型必须与传入值严格相等才命中;
  • case 7 是最后一个分支,位于整个 switch 块末尾,因而可以省略 break(执行流自然离开 switch),这也是官方参考实现恰好只有 4 个 break 的原因。

逐条验收测试:hints 是如何判定答案的

本节挑战文档的 --hints-- 区共列出 8 条自动验收断言。从源码结构看,这些 hint 就是"测试用例",而 curriculum/schema/challenge-schema.js 中定义的 tests 字段要求每个 challenge 必须有 { text, testString } 形式的结构——text 是人类可读的提示语,testString 才是真正会被执行的断言代码。

测试语义可以分成两类:

类别 断言 具体规则
语法约束 编辑器内不得出现 else !/else/g.test(...)
语法约束 编辑器内不得出现 if !/if/g.test(...)
结构约束 至少 4 个 break 语句 code.match(/break/g).length >= 4
行为验证 chainToSwitch("bob") 返回 "Marley" 与参考实现比对
行为验证 chainToSwitch(42) 返回 "The Answer" 同上
行为验证 chainToSwitch(1) 返回 "There is no #1" 同上
行为验证 chainToSwitch(99) 返回 "Missed me by this much!" 同上
行为验证 chainToSwitch(7) 返回 "Ate Nine" 同上
行为验证 chainToSwitch("John") 返回 "" 未匹配输入须保持空字符串
行为验证 chainToSwitch(156) 返回 "" 同上

几条断言背后的设计意图值得展开:

前两条的注释剥离处理。 正则检测前都先经过 __helpers.removeJSComments(code),即先从代码中剔除注释。原因很直接:如果学习者仅仅在注释里写下"if/else"这类字样,不应被误判为违反约束。这说明 freeCodeCamp 对"结构约束类 hint"刻意做了鲁棒性处理——只检测真实代码,不检测注释文本。

"至少 4 个 break"与 fall-through 的关系。 5 个分支需要 4 个 break:在 case 1case 99 之间如果漏掉 breakval === 99 命中的执行流会继续掉进 case 7,把 "Ate Nine" 覆盖掉之前的赋值,行为即被破坏。反过来,若在每个分支后都补上 break(5 个),同样能通过断言——>= 4 只设下限,允许学习者写得更"防御"。

无 default 时的行为兜底。 最后两条断言验证 "John"156 这种未匹配值仍返回 ""。这里没有引入 default 分支,等价于原 if 链没有 else 兜底:未命中任何 case 时,函数直接跳过整个 switch,返回 answer 的初值 ""。这实际上潜移默化地让学习者理解"没有 default 的 switch 在未命中时是什么行为"。

对照同块挑战,理解 switch 的三个必会细节

本节作为 switch 系列收官课,默认学习者已经掌握前三课的知识。把它们连起来就是完整的 switch 知识点闭环,也可作为排查本节报错的排查手册:

  1. case 匹配是严格相等(===:数值、字符串、布尔等类型必须严格一致。参考 Selecting from Many Options with Switch Statements
  2. 省略 break 会向下穿透:这正是"至少 4 个 break"这条 hint 存在的理由;但也有意利用穿透、让多个输入共享同一输出的合法写法,见 Multiple Identical Options in Switch Statements(如 case 1: case 2: case 3: 共用同一段输出)。
  3. default 提供兜底分支:作用等同 if/else 链中最后的 else,且规范上应放在最后,见 Adding a Default Option in Switch Statements

把本节与前三课结合,就构成了完整的判断结构选型能力:何时用 if 链、何时用 switch、switch 内如何合并分支、如何兜底、如何防止误穿透。文档中提到 switch 在"选项很多"时更易写,本质是让表达贴近"一组离散常量 → 一组结果"的查表语义。

在仓库中深入挖掘本节挑战的实现

如果想在仓库里完整追踪这道挑战的"数据链",可以按以下路径查看:

小结

Replacing If Else Chains with Switch 是一道典型的"等价改写"练习:它不要求学习者写出全新逻辑,而是要求用 switch 忠实翻译一段已知正确的 if/else if 链,并满足"无 if/else、至少 4 个 break、8 组输入输出全部一致"的硬性验收。完成这道题的核心收获是三层:

  1. 语法层:掌握 case 写法、break 的防穿透作用、default 的有无与放法;
  2. 语义层:理解 switch 采用严格相等匹配,且无命中、无 default 时直接跳过整个块;
  3. 工程层:在"离散多值 → 结果映射"这种高频场景中,学会用 switch 写出比长串 else if 更清晰、更易维护的分支结构。

对照同块元数据文件 curriculum/structure/blocks/basic-javascript.json 可以看到,switch 四连课被刻意编排在"Logical Order in If Else Statements / Chaining If Else Statements"之后、布尔返回模式之前,是 Basic JavaScript 块内判断与分支主题的收官练习。理解这一编排,就能更好地把握这道题在整条学习路径上的作用:它是从"会写条件判断"走向"会选条件结构"的分水岭。

登录后查看全文
热门项目推荐
相关项目推荐

项目优选

收起
kernelkernel
deepin linux kernel
C
33
18
ops-transformerops-transformer
本项目是CANN提供的transformer类大模型算子库,实现网络在NPU上加速计算。
C++
1.13 K
2.75 K
pytorchpytorch
作为 Ascend for PyTorch 社区的核心组件,TorchNPU 是昇腾专为 PyTorch 打造的深度学习适配插件,使 PyTorch 框架能够直接调用昇腾 NPU,为开发者提供昇腾 AI 处理器的超强算力。
Python
857
1.35 K
docsdocs
暂无描述
Markdown
897
5.8 K
kernelkernel
openEuler内核是openEuler操作系统的核心,既是系统性能与稳定性的基石,也是连接处理器、设备与服务的桥梁。
C
529
593
ops-nnops-nn
本项目是CANN提供的神经网络类计算算子库,实现网络在NPU上加速计算。
C++
915
1.83 K
jiuwenswarmjiuwenswarm
JiuwenSwarm 是一款基于openJiuwen开发的智能AI Agent,它能够将大语言模型的强大能力,通过你日常使用的各类通讯应用,直接延伸至你的指尖。
Python
3.58 K
1.01 K
ops-mathops-math
本项目是CANN提供的数学类基础计算算子库,实现网络在NPU上加速计算。
C++
1.35 K
1.46 K
cann-learning-hubcann-learning-hub
CANN 学习中心仓,支持在线互动运行、边学边练,提供教程、示例与优化方案,一站式助力昇腾开发者快速上手。
Jupyter Notebook
1.01 K
515
AscendNPU-IRAscendNPU-IR
AscendNPU-IR是基于MLIR(Multi-Level Intermediate Representation)构建的,面向昇腾亲和算子编译时使用的中间表示,提供昇腾完备表达能力,通过编译优化提升昇腾AI处理器计算效率,支持通过生态框架使能昇腾AI处理器与深度调优
C++
547
388