03运算符与流程控制

一个 JS 程序,本质就是数据 + 运算符 + 流程控制三件套。 运算符把数据组合成表达式(a + b、x > 10), 流程控制让程序按条件分支(if/switch)或循环(for/while)跑下去。 这一课把这两件武器一次讲完。

约 18 分钟 6 个动手实验 运算 + 流程控制

一、算术运算符与赋值运算符

最熟悉的一组:+ - * / % **。 ** 是 ES7 引入的「幂」:2 ** 3 等于 8。 + 是双面人——两边都是数字就相加,只要有一边是字符串就变成拼接。 所以 '5' + 3 得到字符串 '53',而 '5' - 3 因为减法没有「拼接」概念,字符串被自动转成数字,得到数字 2。

++ 和 -- 是自增 / 自减。前缀(++i)先加再用, 后缀(i++)先用再加——单独一行没差别,写进表达式里就翻车。

算术 + 赋值运算符速查
运算符含义示例结果
+加 / 拼接1 + 2 / '1' + 23 / '12'
-减'5' - 32(自动转数字)
* / /乘 / 除6 / 41.5
%取余(取模)5 % 32
**幂(ES7)2 ** 101024
++ / --自增 / 自减i++ / ++i看位置:先加还是后加
+= -= *= /=算术赋值x += 5x = x + 5 的简写
**= %=幂赋值 / 取余赋值x **= 2x = x ** 2
算术现场:把 a 改成 '5' 字符串再看一遍—— + 变成拼接、 - 却仍是数字减法
++i 先加再用,i++ 先用再加——写在表达式里差别巨大。 实战中能分开写就分开写,单独一行用谁都行,别埋进 arr[i++] 这种地方自找麻烦。

二、比较与逻辑运算符

比较结果是 true / false。=== 严格相等(类型 + 值都相等), == 会偷偷做类型转换,是JS 公认的坑——项目里只许用 ===。

逻辑三剑客:&&(与,全真才真)、||(或,一真就真)、!(非,取反)。 它们还有个隐藏技能——短路:能立刻判断结果时,后面的就不跑了。

ES2020 新加两个狠角色:?? 空值合并(只在 null/undefined 时兜底)、 ?. 可选链(中间任意一环是 null/undefined 就直接返回 undefined,不报错)。

== vs === 速查:能用 === 就别用 ==
比较==(松散)===(严格)
0 与 '0'0 == '0' → true(字符串转数字)0 === '0' → false(类型不同)
null 与 undefinednull == undefined → truenull === undefined → false
'' 与 0'' == 0 → true'' === 0 → false
[] 与 false[] == false → true(绕)[] === false → false
一行一行对比看:把 data.bio 的 null 改成 {bio: 'hi'},可选链和 ?? 的输出会同时变
?? 解决了 || 的老毛病:只要 0、空串、false 合法,就该用 ??,用 || 会被当成「没值」。

三、三元运算符与短路求值

三元 条件 ? 值1 : 值2 是 if / else 的表达式版—— if/else 是语句、不返回值;三元是表达式、能塞进变量和模板字符串。

短路求值是逻辑运算符的副产品:a && b 从左往右找第一个 falsy,找到就返回它,全是真值就返回最后一个真值; a || b 反过来找第一个真值。 实战中 || 常用来给「空值/0」兜底(但注意上面说的 ?? 更稳)。

三元做年龄分级:输入 0~120 的数字,看落到哪一档;下面的「兜底」按钮演示 || 短路
三元嵌套别超过 2 层,再多就读不下去了—— 看到 a ? b : c ? d : e ? f : g 立刻抽成 if/else。if/else 反过来也有规矩—— 嵌套不超过 3 层,否则就是「金字塔噩梦」,先抽函数 / 早返回 / 卫语句。

四、if / else if / else 条件分支

主力武器。if (条件) { ... } else if (条件) { ... } else { ... } 条件用括号包起来,执行的代码块用花括号包起来。

三条工程规矩:① 始终写花括号,哪怕只有一行——不加的话缩进出错就是 bug; ② else if 可以链多个,按顺序判定,第一个满足的就跑;③ 嵌套别超过 3 层, 否则就是「金字塔噩梦」,先抽函数 / 早返回 / 卫语句。

分数 → 等级:输入 0~100 的分数,看输出 A / B / C / D / 无效;输入 105 落到「无效」分支

五、switch 多路分支

当一个变量要按多个固定值分支时,switch 比一长串 else if 更清晰。 经典结构:switch (x) → 多个 case → 每个 case 末尾必须 break, 最后用 default 兜底。

漏写 break 就会「穿透」——命中一个 case 后,下面所有 case 都会跑, 直到遇到第一个 break 或者 switch 结束。多数情况是 bug,但「多个 case 共享同一段代码」时是有意为之。

数字 → 星期:输入 1~7 看「周一」到「周日」;输入 99 走 default 分支
switch 不写 break 会穿透——常见 bug 来源。 一个反例:case 1 漏写 break,会顺路执行 case 2、case 3…… 直到遇到第一个 break 或 switch 收尾。Lint 工具能帮你查,记得开。

六、for 循环

最常用的循环:for (初始化; 条件; 更新) { ... }。 三段都可选:省略初始化就把变量声明写在上面;省略条件就是死循环; 省略更新就靠循环体内手动改。三段都写齐是标准范式。

循环内常用两个控制词:break(跳出整个循环,立刻停) 和 continue(跳过本次,进入下一轮)。

for 家族四种变体:什么时候用哪个
写法适用场景典型用法
标准 for已知循环次数for (let i=0; i<10; i++)
省略段 for复杂初始化 / 步长在体内改for (;;) 死循环,靠 break 出
for...of遍历数组 / 可迭代对象的值for (const x of arr)
for...in遍历对象的键(不推荐遍历数组)for (const k in obj)
for 三连:①1-100 求和 ②1-100 偶数 ③9×9 三角(点击三个按钮分别跑)

七、while 与 do-while

不知道循环次数、只知「满足条件就继续」时,用 while (条件) { ... }——先判后做。 如果条件一开始就是假,循环体一次都不跑。

反过来想「无论怎样先做一次」,就用 do { ... } while (条件)——先做后判, 最典型的场景是输入验证:必须让用户至少输入一次,不合格就一直让他重新输入。

while 求 1+...+100 = 5050;下面用 do-while 演示「输入必须在 1~7 之间」——不满足就再来一次

八、本章小结

  • 算术 + - * / % **,+ 会因字符串而变拼接,- 不会——拼接/相减的区别常考。
  • 比较只用 === 和 !==,避开 == 的隐式类型转换;逻辑 && / || / ! 都是短路求值。
  • ES2020 新增 ??(空值合并)和 ?.(可选链)——兜底字段首选 ??,比 || 更精准。
  • 三元 条件 ? a : b 是表达式版的 if/else,嵌套别超过 2 层。
  • if/else 用卫语句把异常挡在最前面;switch 每个 case 必须 break,否则穿透。
  • for 已知次数、while 条件循环、do-while 至少跑一次;break 跳出整层、continue 跳过本轮。
动手练习:①用 for 输出 1~100 之间的素数,命中时用 console.log,非命中用 continue; ②用 switch 把月份(1~12)转季节(春 3-5 / 夏 6-8 / 秋 9-11 / 冬 12,1,2); ③用三元判断某年是否闰年((y % 4 === 0 && y % 100 !== 0) || y % 400 === 0); ④写一个 userInput ?? '匿名' 的兜底,验证 0 和 '' 都不会被替换。 每题写完用今天的 lab 套路挂按钮跑一遍。