首页
/ freeCodeCamp Basic JavaScript 教程精讲:用逻辑与运算符(&&)合并多重条件判断

freeCodeCamp Basic JavaScript 教程精讲:用逻辑与运算符(&&)合并多重条件判断

2026-09-07 09:15:37作者:丁柯新Fawn

freeCodeCamp 课程体系的 Basic JavaScript 认证路径中,"Comparisons with the Logical And Operator"(对应挑战文件 curriculum/challenges/english/blocks/basic-javascript/56533eb9ac21ba0edf2244d8.md)是一个围绕 && 逻辑与运算符的核心实战关卡。本文将以该挑战文档为主体,从运算符语义、嵌套 if&& 的等价改写、边界值测试到 freeCodeCamp 挑战文件的 YAML/Markdown 结构与校验机制层层展开,帮助你彻底掌握"多条件同时成立"这一 JavaScript 条件分支编程的基础能力。

挑战文档与前置知识背景

这份挑战文档通过 frontmatter(YAML)元数据与 Markdown 正文两部分组成。frontmatter 中声明了唯一的挑战 ID(id: 56533eb9ac21ba0edf2244d8)、标题、challengeType: 1(普通编程题)以及用于生成 URL slug 的 dashedName: comparisons-with-the-logical-and-operator。它位于 JavaScript 基础(Basic JavaScript)模块的比较运算符序列中——紧接其前的是"小于或等于运算符"关卡(56533eb9ac21ba0edf2244d7.md),紧随其后的是"逻辑或运算符"(56533eb9ac21ba0edf2244d9.md)与"引入 else 语句"(56533eb9ac21ba0edf2244da.md)。完成这些关卡后,你将进入 Chaining If Else Statements 等更复杂的多路分支内容。

在学习本关之前,你已经掌握的基础包括:><>=<====== 等比较运算符的返回值语义(全部为布尔值 true/false),以及 if 语句的块级执行流程。

逻辑与运算符(&&)的核心语义

原文定义:The logical and operator (&&) returns true if and only if the operands to the left and right of it are true.

&& 被称为"逻辑与",它是一个二元运算符,接受左右两个操作数(operand),并返回布尔值。其判定规则可以浓缩为:

  • 左右两侧操作数都为真时,整个表达式为 true
  • 除此之外的任意组合(左假右真、左真右假、双双为假),整个表达式均为 false
左操作数 右操作数 左 && 右 结果
true true true
true false false
false true false
false false false

在本挑战中,左右"操作数"通常不是裸的布尔值,而是 val >= 25val <= 50 这类比较表达式。由于比较运算符返回的就是布尔值,因此 val >= 25 && val <= 50 就是在询问"两个子条件是否同时成立"。这也是"并且""同时"这类自然语言在代码中的直接表达。

嵌套 if 与 && 的等价性

如果一次需要判断多个条件,最"笨拙"但直观的做法是把一个 if 嵌套在另一个 if 内部——文档给出的原始版本(description 部分,第 15-22 行)如下:

if (num > 5) {
  if (num < 10) {
    return "Yes";
  }
}
return "No";

执行逻辑如下:只有当 num > 5 为真时才会进入外层代码块,进而判断 num < 10;只有当内层条件也为真,才会 return "Yes"。换句话说,两个条件必须同时满足才返回 Yes,否则落入函数末尾的 return "No"

&& 可以把"嵌套判断"压缩为"单层条件 + 复合逻辑表达式"(第 26-31 行):

if (num > 5 && num < 10) {
  return "Yes";
}
return "No";

两段代码在语义上完全等价:num 落在区间 (5, 10)(不含端点)时返回 Yes,否则返回 No。比较两种写法可以总结出 && 的实战价值:

  • 可读性:一个 if 一个条件表达式,意图一目了然;嵌套写法让代码层级加深、缩进增多。
  • 扁平化:消除了多余的作用域层级,减少花括号配对出错的可能。
  • 易于扩展:以后想增加第三个条件(例如还要 num !== 7),在 && 链上追加即可,而嵌套写法会继续加深一层。

需要注意的是,&& 并非只是 if 嵌套的语法糖,它本身是一个会产生值的表达式,可出现在 if 条件之外的位置(例如 const ok = a && b;)。不过在 JavaScript 中它遵循"短路求值":一旦左侧操作数为假,右侧操作数根本不会被求值,整个表达式立刻短路为左侧的值。这一点在本关的 return 场景中不会带来差异,但当右侧是函数调用等有副作用的代码时就需要特别警惕。

本关任务:改写为单一的 && 条件

进入实操环节。文档的 instructions(第 33-35 行)给出明确目标:

Replace the two if statements with one statement, using the && operator, which will return the string Yes if val is less than or equal to 50 and greater than or equal to 25. Otherwise, will return the string No.

即:用一条含 &&if 语句替换两个 if;当 val 同时满足 val <= 50val >= 25(注意两个条件都含端点,即闭区间 [25, 50])时返回字符串 "Yes",否则返回 "No"

初始种子代码

编辑器初始的种子代码(seed-contents,第 103-118 行)如下:

function testLogicalAnd(val) {
  // Only change code below this line

  if (val) {
    if (val) {
      return "Yes";
    }
  }

  // Only change code above this line
  return "No";
}

testLogicalAnd(10);

这段种子代码中,内外的两个 if (val) 都以参数 val 本身作为条件。JS 中任何非空数值(包括负数)在布尔上下文中都视为真值,因此这段代码对几乎所有入参都会命中内层 return "Yes"——它并不具备"区间判定"能力,只是留给学习者替换的占位逻辑。你的编辑范围被 // Only change code below this line// Only change code above this line 两条注释限定,种子代码在注释外的函数定义、return "No" 与末尾的 testLogicalAnd(10) 调用不应改动。

推荐的解题步骤

  1. 将第一个 if (val) { 的条件替换为 val >= 25(因为题目要求 val 大于或等于 25)。
  2. 删除内层的第二个 if (val) { ... } 层级,让两个条件通过 && 合并:val >= 25 && val <= 50
  3. 保留花括号内的 return "Yes";,以及函数末尾的 return "No";
  4. 检查全文只出现一次 if、一次 &&

隐藏测试(hints)逐条拆解

freeCodeCamp 的每道编程题都会在 --hints-- 区块给出自动化测试断言,由测试运行器逐条对"学习者提交的代码"执行验证。本关的 hints(第 37-97 行)分为"源码结构检查"与"功能行为检查"两类:

源码结构断言

assert(__helpers.removeJSComments(code).match(/&&/g).length === 1);

这条断言先把代码中的 JS 注释剥离(__helpers.removeJSComments),再用正则 /&&/g 统计 && 出现的次数,要求恰好为 1 次——防止你通过拼凑多个 && 绕过练习意图。

assert(__helpers.removeJSComments(code).match(/if/g).length === 1);

同理,这条断言要求全文只出现一个 if,直接约束了你必须把两个 if 合并成一条语句,而不是仅仅在嵌套里再加条件。

功能行为断言

功能断言直接调用你写出的 testLogicalAnd(val) 函数并比对返回值,覆盖区间内外的典型采样点:

断言 入参 val 期望返回 说明
testLogicalAnd(0) 0 "No" 远小于 25,左侧条件不成立
testLogicalAnd(24) 24 "No" 临界点下方:24 >= 25 为假
testLogicalAnd(25) 25 "Yes" 左端点包含25 >= 25 为真且 25 <= 50 为真
testLogicalAnd(30) 30 "Yes" 区间内部
testLogicalAnd(50) 50 "Yes" 右端点包含50 <= 50 为真
testLogicalAnd(51) 51 "No" 临界点上方:51 <= 50 为假
testLogicalAnd(75) 75 "No" 远大于 50,右侧条件不成立
testLogicalAnd(80) 80 "No" 同上

这个采样点设计是理解本题的关键:0/24 探测左边界之下,25 验证左边界包含,50 验证右边界包含,51/75/80 探测右边界之上。任何一个把 >= 误写成 >、或把 <= 误写成 < 的实现,都会在 25 或 50 这两个边界点上失败。由此可见,判断数值落在"闭区间"时必须使用大于等于/小于等于配合 &&

参考解答与代码逐行分析

文档 --solutions-- 区块(第 120-129 行)给出了标准解:

function testLogicalAnd(val) {
  if (val >= 25 && val <= 50) {
    return "Yes";
  }
  return "No";
}

逐行分析这段最优解:

  • if (val >= 25 && val <= 50):单个 if,复合条件 = 左界比较 && 右界比较。两个比较表达式均返回布尔值,&& 要求两者同时为 true,从而精确圈定闭区间 [25, 50]
  • 条件为真时进入代码块 return "Yes";,提前结束函数执行。
  • 条件为假(val 落于区间之外)时,代码块被跳过,函数继续执行末行 return "No";

整个函数无任何嵌套层级、无 else、无多余变量,是"用一条条件语句表达互斥两分支"的教科书写法。它与该序列前一关 Comparison with the Less Than Or Equal To Operatorval <= 12val <= 24 的多重 if 分界写法形成对比:单边比较用顺序 if,双边区间判定则用 && 合并。

拓展:短路求值与链式区间判断

在上述解答基础上,你可以尝试把这些边界知识迁移到更实际的场景:

// 判断成绩是否为"合格"(60-100,含两端)
function isPass(score) {
  return score >= 60 && score <= 100;
}

// 区间反转写法(逻辑等价,但可读性更贴近自然语言)
function inRange(val, min, max) {
  return val >= min && val <= max;
}

在 freeCodeCamp 后续关卡中,你会看到 &&||logical or 挑战)常被用于同一函数内的不同分支判断。二者需要辨析清楚:

  • a && b:a 和 b 为真才为真(交集思维);
  • a || b:a 或 b 任一为真即为真(并集思维)。

例如判断 val 不在 [25, 50] 内时,直觉写法是"小于 25 或大于 50",此时应当用 ||if (val < 25 || val > 50) return "No";。这也正是紧随其后的 logical or 关卡(其种子代码同样是两个待合并的 if)所训练的对称技巧。两个关卡合在一起,构成了"如何把一个取值范围问题表达为复合布尔表达式"的完整练习闭环。

从文档格式看 freeCodeCamp 挑战的运行机制

如果你希望深入理解这份 .md 是如何变成可交互题目的,可以观察文件的 YAML/Markdown 结构和仓库校验代码。每个挑战文件都由固定 section 构成:--description--(讲解)、--instructions--(任务)、--hints--(自动化断言,每条 hint 前是给人看的说明文本,后面是断言代码)、--seed----seed-contents--(种子代码)、--solutions--(参考答案)。frontmatter 的 challengeType: 1 声明这是需要写代码的"算法/逻辑题"类型,forumTopicId 关联历史论坛讨论。

仓库使用 Joi 对全部挑战做 schema 级校验,见 curriculum/schema/challenge-schema.js。从该文件中可以看到(第 180-184 行):challengeType 被要求为 0-33 的必填数值,dashedName 必须匹配 ^[a-z0-9-]+$ 的小写短横线 slug 格式,与本文挑战 ID 内嵌于文件名、URL 友好命名的形式一一对应。因此修改任何一道挑战的元数据或正文结构时,都必须保证它仍然能通过这套 Joi schema 与配套的 curriculum 测试,否则课程无法正常构建与呈现。

在浏览器端练习环境中,--seed-contents-- 会被加载进代码编辑器,// Only change code below this line 这类标记决定了哪些区域对学习者可编辑,而 hints 中的断言则通过测试辅助对象(__helpers.removeJSComments 等)在学习者每次运行时执行,逐条给出通过/失败反馈。你甚至可以在浏览器开发者工具中手动逐条执行 hints 里的断言,借此理解每一条检查的真实含义。

常见错误与排查清单

完成本关时,典型的报错场景与原因如下:

  • 断言"应恰好出现一次 if"失败:说明你仍保留了嵌套的两个 if,需要把外层条件补全为 val >= 25,并删掉整个内层 if
  • 断言"应恰好出现一次 &&"失败:多写了 &&,例如额外对 val 加了 val >= 0 之类的冗余判断。
  • testLogicalAnd(25)testLogicalAnd(50) 返回错误:多半把 >=/<= 写成了 >/<。闭区间判定必须使用含等号的比较运算符。
  • testLogicalAnd(24) 返回 "Yes":说明左边界条件写反(如 val <= 25),注意 && 两侧的子条件都要各自正确。
  • 修改到了注释标记以外的代码:请通过"重置"恢复种子代码,只在 // Only change code below this line 与上方注释之间编辑。

自查时可以把 testLogicalAnd(10); 末尾调用换成不同取值逐一手动运行:2425305051,对照上文的期望结果表检查输出是否一致。

小结:本关在 JavaScript 学习路径中的位置

"Comparisons with the Logical And Operator" 看起来只是把一个嵌套 if 改写为 && 的小练习,但它背后承载的能力点是复合布尔逻辑:将日常语言中的"同时""并且"翻译为 &&,将区间、多重约束落到单条 if 条件中。配合前序的比较运算符关卡、后续的 ||else ifelse 链(Introducing Else StatementsIntroducing Else If Statements)与 Chaining If Else Statements,你将逐步具备写出清晰、健壮的多路分支逻辑的能力——这也是后续编写真实业务校验(如表单年龄/分数范围验证、权限判定)时最频繁使用的语言基础之一。掌握 >=<=&& 的组合、理解闭区间边界语义,就是迈过这一门槛的关键一步。

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