if 语句的结构
if 语句只在条件为真时才执行一段代码。它的结构是:一个关键字、括号里的条件,以及花括号里的代码块:
条件 age >= 18 的结果是 true,所以代码块会执行。如果 age 是 16,条件就会是 false,JavaScript 会完全跳过这个代码块。
当代码块只有一条语句时,花括号在技术上是可选的,但请始终写上。不带花括号的 if 语句是一个经典的 bug 来源:以后有人加了第二行,却忘了这一行其实并不在代码块里。
else:兜底分支
把 if 和 else 搭配起来,就能在条件为假时执行另一段代码:
两个分支中恰好只有一个会执行。不会两个都执行,也不会一个都不执行。else 没有自己的条件,它负责兜住“if 为假”的所有情况。
else if:从多个选项中选一个
当情况多于两种时,用 else if 把它们串起来。JavaScript 按顺序检查每个条件,遇到第一个为真的就停止:
只有一个分支会执行。一旦某个条件匹配,其余的都会被跳过,即使它们也为真。这就是顺序很重要的原因:如果你把链条反过来,先检查 score >= 60,那么所有 60 分以上的人都会得到 D。
最后的 else 是可选的,但写上它能让你的意图更清楚:“如果其他条件都不匹配,就执行这里。”
条件可以是任何表达式
括号里的内容不一定是比较运算。它可以是任何表达式,JavaScript 会把结果转换成布尔值:
非空字符串是真值。0 和空字符串是假值,所以当 items.length 为 0 时会走 else 分支。这是 JavaScript 中“检查是否有内容”的标准写法。
假值的完整列表很短,值得记住:false、0、-0、0n、""、null、undefined 和 NaN。其他所有值都是真值,包括 "0"、"false"、[] 和 {}。最后两个常常让人上当。
组合条件:&& 和 ||
用 &&(与)和 ||(或)来组合条件:
&& 要求两边都是真值,|| 要求至少一边是真值。两者都会短路:&& 遇到第一个假值就停止,|| 遇到第一个真值就停止。当第二个条件有副作用或者可能抛出异常时,这一点就很重要:如果 user 是 null,user && user.name 会安全地返回 undefined,而不会报错。
混合使用时,用括号把逻辑包起来,让优先级一目了然:
不加括号的话,&& 的优先级比 || 高,而这通常和自然的阅读习惯相反。
== 与 ===(请用 ===)
在 if 中判断相等时,用 === 和 !==,而不是 == 和 !=:
== 在比较之前会转换类型,从而导致一些意外,比如 "" == 0 为 true,null == undefined 也为 true。=== 比较时不做类型转换:类型相同且值相同才相等。默认使用 ===。唯一常见的例外是 x == null,它可以一次性检查 null 和 undefined。
三元运算符
在两个值之间做选择时,三元运算符 condition ? a : b 通常比完整的 if/else 更简洁:
三元运算符是一个表达式,它会产生一个值。这是它和 if/else(一条语句)的关键区别。需要结果时(给变量赋值、返回值、拼接字符串)用三元运算符;执行有副作用的操作时用 if/else。
三元运算符可以链式嵌套,但可读性会断崖式下降:
// Don't do this:
const grade = score >= 90 ? "A" : score >= 80 ? "B" : score >= 70 ? "C" : "F";
如果要链式嵌套,就回到 else if。
嵌套 if 与扁平的 else if
有时一个条件只有在另一个条件成立时才有意义。这种情况下嵌套没问题:
但嵌套三四层就是一种代码坏味道了。用提前返回或者合并条件把它展平:
提前返回让每个分支都很短,而且处在同一缩进层级。这比层层嵌套的 if 金字塔好读得多。
常见陷阱:在 if 中赋值
= 是赋值,=== 是比较。在条件中把两者搞混是一个经典 bug:
status = "done" 会把 "done" 赋给 status,并且表达式的值就是 "done",这是真值,所以代码块总会执行,而你已经在不知不觉中覆盖了这个变量。代码检查工具(linter)能发现这个问题,严格模式则不能。多加小心,想比较时就用 ===。
下一步:switch
当你要把一个值和许多可能的匹配项进行比较时,长长的 else if 链就开始显得重复。JavaScript 的 switch 语句正是为这种情况设计的,它在 break 和贯穿(fall-through)方面也有自己的特点,这就是下一页的内容。
常见问题
JavaScript 中如何写 if/else 语句?
在 if 后面的括号里写条件,然后是花括号包起来的代码块。接着写 else 和另一个代码块作为兜底分支。例如:if (age >= 18) { console.log('adult'); } else { console.log('minor'); }。条件可以是任何表达式,JavaScript 会把它转换成布尔值。
JavaScript 中 else if 和嵌套 if 有什么区别?
else if 把多个条件串联起来,只有一个分支会执行:JavaScript 按顺序检查每个条件,遇到第一个匹配的就停止。嵌套 if 则是把一个 if 放进另一个里,通常用于只在第一个条件为真时才检查第二个条件。扁平的 else if 链几乎总是比层层嵌套的 if 更容易阅读。
什么时候应该用三元运算符代替 if/else?
当你在表达式中从两个值里选一个时,用三元运算符 condition ? a : b:给变量赋值、从函数返回、拼接字符串。当分支执行的是有副作用的语句,或者任何一边不止是一个简短的表达式时,坚持用 if/else。三元运算符一旦链式嵌套,很快就变得难以阅读。
为什么 JavaScript 中 if (0) 的表现和 if (false) 不一样?
其实没有不一样,两者都会跳过代码块。JavaScript 会把条件转换成布尔值,而 0、''、null、undefined、NaN 和 false 都是假值。真正的坑在于,'0'(非空字符串)和 [](空数组)这类值是真值,这会让从其他语言过来的人感到意外。