B 币安 · 全球最大的加密货币交易所币安 注册 → AD OKX OKX · 全球领先的加密货币交易所OKX 注册 → AD
💻 编程基础 · 第3讲 / 10

条件语句:根据情况走不同的路

条件语句是把算法的第二种要素“条件”写成代码的方法。把条件写准确,大部分工作就是明确规定在边界上该走哪一边。

⏱ 约20分钟 ✍️ 练习题 5 道 🧪 代码练习 4 题 更新 2026-10-09
🎯 本讲学习目标
  • 能用if、else if、else按正确的顺序写出多个分支的条件
  • 能用比较运算符和&&、||、!构造条件,并说明为什么要用===代替==
  • 能区分truthy和falsy的值,并预测0、空字符串在条件中会被如何对待
  • 能挑选边界值,测试条件语句是否正确运行

1.`if`与`else`:设置岔路口

第1讲说过,代码从上到下依次执行。条件语句在这条流程上设置岔路口。写if (条件) { … },只有括号里的条件为真时才执行花括号里的代码,为假就跳过。如果条件为假时另有要做的事,就在后面接上else { … }。两条路中只会恰好执行一条。

条件的位置要写结果为true或false的表达式。第2讲的布尔值正是在这里派上用场。age >= 19在age大于等于19时为true,否则为false。先用console.log把条件表达式打印出来,就能预先知道条件语句会走哪一边;条件语句没有按预想运行时,这有助于找到原因。

花括号里的代码缩进两格,让人一眼看出“这段代码属于这个条件”。运行环境不看缩进,而是靠花括号区分;人却是靠缩进来读结构的。缩进错乱的代码会误导读者,所以要始终对齐。即使花括号里只有一行代码,也最好不要省略花括号,这样以后添加代码时不容易出错。

先打印条件表达式的值,就能看出会走哪条分支
const age = 17;
console.log(age >= 19);
if (age >= 19) {
  console.log("成人票");
} else {
  console.log("青少年票");
}
输出
false
青少年票

2.`else if`:多个分支从上往下依次检查

分支有三条以上时,就接上else if。运行环境从上往下逐个检查条件,只执行第一个为真的分支,其余的全部跳过。如果没有任何条件为真,就执行最后的else。所以else负责的是“上面所有情况之外的全部剩余情况”。

因为“只执行第一个为真的”这条规则,条件的顺序很重要。如果按分数评等级,就必须从高的标准开始依次检查。95分既满足score >= 90,也满足score >= 80;如果先写80的条件,95分就会得到B。从高标准往下走,后面的条件就可以默认“前面的条件已经为假”,也就不必像score >= 80 && score < 90那样把范围的两头都写出来。

写条件语句之前先整理成表格,就容易发现漏掉的区间和重叠的区间。像下面的例子那样,定好“90以上A,80以上B,70以上C,其余F”,照着表格从上往下搬过去即可。等级标准只是示例,实际标准因学校、公司而异。

从高标准开始检查,只会执行第一个为真的分支
const score = 85;
if (score >= 90) {
  console.log("A");
} else if (score >= 80) {
  console.log("B");
} else if (score >= 70) {
  console.log("C");
} else {
  console.log("F");
}
输出
B
明明是95分却输出B——第二条分支永远到达不了
// 顺序写错的例子
const s = 95;
if (s >= 80) {
  console.log("B");
} else if (s >= 90) {
  console.log("A");
}
输出
B

3.比较运算符与`===`和`==`

比较两个值的运算符有:大于(>)、小于(<)、大于等于(>=)、小于等于(<=)、等于(===)、不等于(!==)。结果总是true或false。比较是否相等时如果只写一个=,就不是比较,而成了放入值的赋值,请务必注意。这个错误非常常见,有时还会不报错、悄悄地出现离谱的行为。

JavaScript里的“等于”有两种。===(严格相等)要求数据类型和值都相同才是true。==(宽松相等)在数据类型不同时,会先做第2讲看到的隐式类型转换再比较。所以1 == "1"是true,0 == ""也是true。由于规则复杂、难以预料,几乎所有编程指南和检查工具都建议只用===和!==。本课程也始终使用===。

字符串之间也可以比较。===要求一个字符都不差,所以"小明" === "小明 "(末尾多一个空格)是false。比较用户输入时,常常因为前后的空格而对不上,第7讲会学习用trim整理的方法。对字符串使用<、>时,会按接近字典顺序的字符编码顺序比较;就像"10" < "9"是true一样,看起来像数字的字符串会被比得一塌糊涂,所以要先转成数字。

==在类型转换后才比较,结果会出乎意料
console.log(3 > 2, 3 >= 3, 3 !== 3);
console.log(1 === "1", 1 == "1");
console.log(0 == "", 0 === "");
console.log(null == undefined, null === undefined);
输出
true true false
false true
true false
true false
看起来像数字的字符串,要转成数字后再比较
console.log("小明" === "小明 ");
console.log("10" < "9", 10 < 9);
console.log(Number("10") < Number("9"));
输出
false
true false
false
比较运算符一览
运算符含义例子结果
===数据类型和值都相同5 === 5true
!==不相等(严格)5 !== "5"true
> / <大于 / 小于3 < 2false
>= / <=大于等于 / 小于等于60 >= 60true
==类型转换后相等(不使用)1 == "1"true

4.逻辑运算符:并且`&&`、或者`||`、不是`!`

要把多个条件组合起来,就用逻辑运算符。A && B只有A和B都为真时才为真;A || B只要有一个为真就为真。!A把真和假颠倒过来。“是会员并且买满3万韩元”用&&,“是会员或者买满3万韩元”用||。日常说话时“并且”“或者”用得比较随意,所以用语言定好条件后,最好再确认一次到底是哪一种。

&&和||只看左边就能确定答案时,就不再计算右边。在A && B中,A为假时不管B如何结果都是假,所以不看B;在A || B中,A为真时不看B。利用这一点写成user !== null && user.age >= 19,user为null时就不会读取右边,从而避开第2讲见过的TypeError。如果调换顺序,这层保护就没有了。

在一个表达式里混用&&和||时,&&先计算。不过,与其背下这个优先级来用,不如用括号把意图表达出来,安全得多。表示范围时,如果像数学那样写成10 <= x <= 20,虽然不会报错,却不会按本意运行。一定要拆成两个比较来写,比如x >= 10 && x <= 20。

虚构的网店条件
const isMember = false;
const total = 32000;
console.log(isMember && total >= 30000);
console.log(isMember || total >= 30000);
console.log(!isMember);
输出
false
true
true
10 <= x先变成true,true <= 20再被转换成1 <= 20,于是为真
const x = 25;
console.log(10 <= x <= 20); // 不会按本意运行
console.log(x >= 10 && x <= 20);
输出
true
false

5.`truthy`与`falsy`:不是布尔值也能当条件

在if的括号里放入不是布尔值的值,也不会报错。JavaScript会把那个值转成真或假来判断。被当作假的值(falsy)是固定的几个:false、0、-0、0n、空字符串""、null、undefined、NaN。不在这个名单里的值全部被当作真(truthy)。空数组[]和空对象{}、文字"0"和"false"也都是truthy,这一点常常让人搞混。

得益于这个性质,可以把“如果有值”简短地写成if (name) { … }。但这里有个陷阱。在个数、金额中,0是正常的值,却是falsy。用if (stock)检查库存为0件的商品,“没有库存信息”和“库存为0件”就会进入同一条分支。这也是AI写的代码里常见的错误。

所以,当你清楚自己要确认什么时,就把条件写具体。要看值是否为空,写stock === null或stock === undefined;要看是否大于0,写stock > 0;要看是否为空字符串,写name === ""。想知道某个值是不是truthy,可以用Boolean(值)直接确认。

"0"和空数组是truthy
console.log(Boolean(0), Boolean(""), Boolean(null));
console.log(Boolean(NaN), Boolean(undefined));
console.log(Boolean("0"), Boolean("false"));
console.log(Boolean([]), Boolean(-1));
输出
false false false
false false
true true
true true
要把0当作正常值处理,就把条件写具体
const stock = 0;
if (stock) {
  console.log("可以购买");
} else {
  console.log("没有库存信息?"); // 明明是0件却来到这里
}
if (stock === null) {
  console.log("没有库存信息");
} else if (stock > 0) {
  console.log("可以购买");
} else {
  console.log("已售罄");
}
输出
没有库存信息?
已售罄

6.边界值:条件语句总在边界上出错

条件语句的错误大多发生在边界上。把“60分及以上及格”写成score > 60,60分就会不及格。只用59分和61分测试,是发现不了这个错误的。所以检查条件语句时,一定要放入紧挨边界下方、边界本身、紧挨边界上方的值。再加上最小值(0)和最大值(100),以及不该出现的值(负数、超过100),大部分错误都会暴露出来。

从用语言制定规则时起,就要把边界说清楚。“满19岁及以上”“满3万韩元及以上包邮”“超过10件打折”中,“及以上”是>=,“超过”是>,“及以下”是<=,“未满”是<。需求如果像“从3万韩元起”这样含糊,写代码之前就该确认正好3万韩元算哪一边。拜托AI写代码时,用语言把边界写清楚,结果也会准确得多。

把要检查的值整理成表格,它就直接成了测试用例。本课程练习场的评分器做的也是同样的事:放入事先定好的输入,与期望值比较。第5讲学了函数,就能更轻松地编写这样的测试;第10讲则会用这种方法检验AI写的代码。

检查“60分及以上及格”(0~100分)的测试值
输入选择的理由期望结果错写成`score > 60`时
59紧挨边界下方不及格不及格
60边界本身及格不及格(发现错误)
61紧挨边界上方及格及格
0 / 100最小值、最大值不及格 / 及格不及格 / 及格
-5 / 120不该出现的值按无效分数处理不及格 / 及格(没有检查)
例题这是虚构的网店规则:“订单金额满30,000韩元或者是会员,运费0韩元,否则3,000韩元”。请挑选检查这条规则的测试值,并用代码确认结果。
const orders = [[29999, false], [30000, false], [0, true]];
for (const [total, isMember] of orders) {
  let fee = 3000;
  if (total >= 30000 || isMember) {
    fee = 0;
  }
  console.log(total, isMember, fee);
}
输出
29999 false 3000
30000 false 0
0 true 0
  1. 第1步 找边界:金额的边界是30,000韩元,而且是“满……及以上”,所以用>=。是否会员有真、假两种。
  2. 第2步 挑测试值:非会员选29,999韩元和30,000韩元,再选一个会员的0韩元(看金额极小时会员是否也免运费)。
  3. 第3步 写条件:total >= 30000 || isMember为真就是0,否则是3000。
  4. 验算:只有29,999韩元的非会员应为3,000韩元,其余都应为0韩元。如果30,000韩元得到3,000韩元,就是错用了>。
答案29,999韩元(非会员)→ 3000,30,000韩元(非会员)→ 0,0韩元(会员)→ 0
示例代码里的for … of是第4讲要学的循环,像[29999, false]这样用方括号括起来的列表是第6讲要学的数组。const [total, isMember]是把列表的第一个、第二个值依次放进两个名字的语法。现在只要看懂“把情况一个个取出来,放进同一个条件语句试一试”就可以了。

📌 要点总结

  • if、else if、else从上往下检查,只执行第一个为真的分支——顺序很重要
  • 比较是否相等时始终用===、!==——==在类型转换后才比较,难以预料
  • &&是全部为真,||是有一个为真,!是取反;范围要拆开写成x >= 10 && x <= 20
  • falsy包括false、0、""、null、undefined、NaN等;0是正常值时要把条件写具体
  • 条件语句要用边界下方、边界本身、边界上方、两端的值和无效值来测试

✍️ 练习题

请先自己作答,再展开“答案与解析”。

Q1. 当const s = 95;时,if (s >= 80) {…B…} else if (s >= 90) {…A…}输出的是?

⭕ 回答正确

❌ 再想一想

答案与解析
答案 ② B

只执行第一个为真的分支。95已经满足s >= 80,所以输出B,第二条分支连检查都不会检查。应该从高标准开始写。

Q2. 下面哪一个的结果是true?

⭕ 回答正确

❌ 再想一想

答案与解析
答案 ③ 1 == "1"

==会把字符串"1"转成数字后再比较,所以是true。===在数据类型不同时为false。正因为这种难以预测,才使用===。

Q3. 下面哪一个不是falsy(即是truthy)的值?

⭕ 回答正确

❌ 再想一想

答案与解析
答案 ③ "0"

文字"0"不是空字符串,所以是truthy。数字0、空字符串、null都是falsy。

Q4. 测试判断“满19岁及以上为成年人”的条件语句时,一定要放入的三个年龄是?

⭕ 回答正确

❌ 再想一想

答案与解析
答案 ② 18、19、20

紧挨边界下方(18)、边界本身(19)、紧挨边界上方(20)。如果19没有被判为成年人,就是错用了>。

Q5. 请写出判断x是否在10以上、20以下(含两端)的条件表达式。

答案与解析
参考答案 x >= 10 && x <= 20

10 <= x <= 20会把前一个比较的结果(true/false)再拿去和20比较,所以不会按本意运行。必须用&&把两个比较连起来。

🧪 代码练习

用条件语句完成函数的练习。评分器会放入包括边界值在内的多种输入来试。

代码只在本浏览器内的隔离环境中运行,不会发送到服务器。无法访问网络,超过2秒会自动停止。改过的代码只保存在此浏览器中。按 Ctrl+Enter(⌘+Enter)运行,Tab 键输入两个空格(先按 Esc 再按 Tab 可跳到下一项)。

浏览器脚本未开启,无法运行代码,但题目、初始代码、自动检查项和参考答案都可以直接阅读。

1判断是否成年

isAdult(age)在年龄age(数字)满19岁及以上时返回true,否则返回false。

自动检查
  • isAdult(18)期望值 false
  • isAdult(19)期望值 true
  • isAdult(20)期望值 true
  • isAdult(0)期望值 false
💡 提示

“及以上”包含边界本身。放入19试试看。

查看参考答案
function isAdult(age) {
  return age >= 19;
}

2按分数评等级

grade(score)接收0~100分的分数,90及以上返回"A",80及以上返回"B",70及以上返回"C",其余返回"F"。

自动检查
  • grade(100)期望值 "A"
  • grade(90)期望值 "A"
  • grade(89)期望值 "B"
  • grade(70)期望值 "C"
  • grade(69)期望值 "F"
  • grade(0)期望值 "F"
💡 提示

从高标准开始检查。遇到return函数就立即结束,后面的条件不会再看。

查看参考答案
function grade(score) {
  if (score >= 90) {
    return "A";
  } else if (score >= 80) {
    return "B";
  } else if (score >= 70) {
    return "C";
  } else {
    return "F";
  }
}

3计算运费

这是虚构的网店规则。shippingFee(total, isMember)在订单金额total满30000及以上或者是会员(isMember为true)时返回0,否则返回3000。但订单金额在0及以下(空订单)时,不论是否会员都返回0。

自动检查
  • shippingFee(29999, false)期望值 3000
  • shippingFee(30000, false)期望值 0
  • shippingFee(5000, true)期望值 0
  • shippingFee(0, false)期望值 0
  • shippingFee(1, false)期望值 3000
💡 提示

先把空订单筛掉,再检查total >= 30000 || isMember。

查看参考答案
function shippingFee(total, isMember) {
  if (total <= 0) {
    return 0;
  }
  if (total >= 30000 || isMember) {
    return 0;
  }
  return 3000;
}

4门票价格与无效输入

这是虚构的博物馆门票。ticketPrice(age)在未满7岁时返回0,7岁及以上、未满19岁返回3000,19岁及以上、未满65岁返回6000,65岁及以上返回0。年龄为负数或不是数字(typeof age !== "number")时返回null。

自动检查
  • ticketPrice(6)期望值 0
  • ticketPrice(7)期望值 3000
  • ticketPrice(19)期望值 6000
  • ticketPrice(65)期望值 0
  • ticketPrice(-1)期望值 null
  • ticketPrice("20")期望值 null
💡 提示

在最前面检查typeof age !== "number" || age < 0,后面的条件就只处理正确的数字了。“未满”是<。

查看参考答案
function ticketPrice(age) {
  if (typeof age !== "number" || age < 0) {
    return null;
  }
  if (age < 7) {
    return 0;
  } else if (age < 19) {
    return 3000;
  } else if (age < 65) {
    return 6000;
  }
  return 0;
}

🤖 可以这样问 AI

复制后把 [ ] 部分换成你的情况。不要直接相信回答,请与正文对照核实。

把条件规则写成代码之前

我想把下面的规则写成JavaScript条件语句。在写代码之前,先就边界值(及以上、超过、及以下、未满)含糊的地方向我提问,再把所有情况整理成“输入—期望结果”表格,让表格的每一行都能成为一个测试用例。规则:[规则说明]

审查AI写的条件语句时

请逐一检查下面的条件语句里是否有:(1) 因为`else if`的顺序而永远到达不了的分支,(2) 使用了`==`,(3) 把0或空字符串当作`falsy`误筛掉的地方,(4) 边界值与规则不符的地方。每个问题都请附上能暴露它的输入值。规则:[规则] 代码:[粘贴代码]

想练习对真假值的感觉时

请出10道关于JavaScript的`truthy`、`falsy`以及`===`/`==`比较的预测题。每道题都问`if (值)`会走哪条分支,先把答案藏起来,等我回答后再连同理由一起告诉我。

🧰 相关工具

可以当场检查、整理本讲涉及的 JSON、正则表达式和文本的工具。请不要粘贴真实的个人信息或密码。

参考
  • MDN Web Docs — JavaScript指南(Guide)中的控制流与错误处理(if...else)、表达式与运算符
  • MDN Web Docs — Falsy、Truthy术语说明,相等性判断(Equality comparisons and sameness)
  • 软件测试入门书中关于边界值分析的一般内容

达成全部学习目标后,请点击完成。

💻 编程基础

  1. 1什么是程序:把事情拆成顺序、条件和循环的思维
  2. 2值、变量与数据类型:给值贴上名字标签
  3. 3条件语句:根据情况走不同的路
  4. 4循环 — 让同一件事准确地重复多次
  5. 5函数 — 拆成一个个有名字的小机器
  6. 6数组与对象 — 装载和处理数据
  7. 7字符串与文本处理——截取、查找、替换文字
  8. 8调试与读懂错误——把红字变成线索
  9. 9简单的自动化示例——用代码做表格计算和文本整理
  10. 10阅读并检验 AI 写的代码——测试、安全、许可证与个人信息
📚 推荐阅读
📊Using AI for Spreadsheets, and Checking the Formulas→ 💻AI Coding Assistants: Security and Licence Risks→ 💬Practising Conversation in a Foreign Language with AI→ ⚙️Finding Work Tasks Worth Automating with AI→
← AI时代基础学力课程