Skip to content

运算符与分支结构 (分支语句 条件语句)(Day3 2/3) ​

本页对应 Day03_JavaScript,共 6 段视频,约 43 分钟。

学习目标 ​

  1. 能正确书写 if 单向分支语法,包括条件表达式、大括号和缩进,并根据条件真假预测分支内语句是否执行。
  2. 能使用 if...else 实现双向分支,说明两条分支必执行其一,并能根据条件预测程序输出。
  3. 能使用三元运算符实现简单的双向分支,并指出其仅适合单条表达式语句的局限性。
  4. 能使用 prompt 获取用户输入并进行数值转换,结合比较运算符和逻辑运算符完成成绩判断。
  5. 能分别使用多个单向 if、if...else 嵌套、if...else if...else 实现成绩等级判断,并比较三种写法的条件复杂度、判断次数和可读性。
  6. 能按缩进规范编写嵌套分支和多向分支,并解释 else if 的条件判断与执行流程。

知识点 ​

本节说明与笔记原代码 ​

本节笔记是“回顾”:数据类型转换与运算符。需要先说明一点:你给的转写稿记录的是 if 单向分支、双向分支、多向分支和三元运算符,与本节“回顾”笔记的主题并不一致。为避免把分支结构硬塞进类型转换里造成编造,下面只按笔记内容扩写;转写稿中的分支内容不混入本节。

笔记原代码如下,保留原样:

js
1. 数据类型转换
   1.1 数据类型转换规则
       ① 转为number
         string: 纯数字字符串、空字符串
         boolean: true->1 false->0
         null: 0
         undefined: NaN
	    ② 转为 stirng
	    ③ 转为 boolean
	      false: 0、NaN、空字符、null、undefined
	1.2 强制类型转换
       Number()	parseInt() parseFloat()
       String()
       Boolean()
   1.3 自动类型转换
       根据所在的运算环境自动类型转换

2. 运算符
   2.1 算术
       + - * / % + - ++ --
   2.2 关系
       > < >= <=
       == != === !==
   2.3 逻辑
       && || !
   2.4 赋值
       = += -= *= /= %= +=
   2.5 其他运算符
       typeof , +

数据类型转换规则:先记“目标类型” ​

为什么需要:JS 是动态类型语言,同一个值参与运算、比较、判断时,经常会被转换成另一种类型。不掌握规则,就会出现“明明写的是数字,结果却拼接成字符串”的问题。
怎么想:不要背“某个值是什么类型”,而要问“现在要转成谁”。笔记把目标分成三类:转 number、转 string、转 boolean。
怎么做:转 number 时,纯数字字符串和空字符串可转;true -> 1、false -> 0、null -> 0、undefined -> NaN。转 boolean 时,假值列表是:0、NaN、空字符、null、undefined,其余按笔记规则为真。
易错点:空字符串转数字是 0,不是 NaN;undefined 转数字是 NaN;字符串 "0" 转布尔是 true,因为它是非空字符串。不要把“看起来像 0”当成假值。

强制类型转换:显式控制结果 ​

为什么需要:自动转换有时不够直观,强制转换能让代码意图更清楚,也方便调试。
怎么想:先确定我要“整体转换”还是“解析一部分”。Number() 是整体转换;parseInt()、parseFloat() 是从左到右解析;String() 转字符串;Boolean() 转布尔。
怎么做:例如 Number("12") 得 12,Number("") 得 0,Number("12px") 得 NaN;parseInt("12px") 得 12,parseFloat("12.5px") 得 12.5;String(123) 得 "123";Boolean(0) 得 false,Boolean("0") 得 true。
易错点:Number("12px") 与 parseInt("12px") 结果不同;Boolean("false") 是 true,因为非空字符串为真;parseInt() 还有进制参数,初学时先别乱传第二参数。

自动类型转换:看“运算环境” ​

为什么需要:很多 bug 不是显式写错,而是隐式转换导致。理解自动转换,才能解释运行结果。
怎么想:看当前运算符“期待什么类型”。算术运算通常期待数字,但 + 特殊:只要一边是字符串,就可能做拼接。
怎么做:"5" - 2 得 3;"5" + 2 得 "52";true + 1 得 2;null + 1 得 1;undefined + 1 得 NaN。关系比较时也要注意两边类型。
易错点:+ 既可能加法也可能拼接;== 会做类型转换,=== 同时比较类型和值;NaN 不等于任何值,包括它自己。

算术与关系运算符:先看操作数类型 ​

为什么需要:运算符是表达式的基础,类型转换又常发生在运算符两侧。
怎么想:算术运算符 + - * / % 中,先判断 + 是否遇到字符串;++、-- 是自增自减。关系运算符 > < >= <= 和 == != === !== 要区分“相等比较”和“全等比较”。
怎么做:写表达式后,先用 typeof 看操作数类型,再判断结果。比较相等时优先用 ===、!==,避免隐式转换。
易错点:"10" < "9" 与 10 < 9 结果可能不同,因为两边都是字符串时按字符串规则比较;== 容易把 "1" 和 1 判为相等。

逻辑、赋值与其他运算符:别把返回值想当然 ​

为什么需要:逻辑运算符常用于条件组合,赋值运算符用于更新变量,typeof 和一元 + 常用于类型判断与转换。
怎么想:&&、||、! 中,! 一定返回布尔值;&&、|| 会按操作数真假决定返回哪个操作数。赋值运算符 = += -= *= /= %= 中,+= 可能做加法,也可能做字符串拼接。typeof 返回类型字符串;一元 + 可把操作数转成数字。
怎么做:需要布尔结果时可用 !!value;需要数字转换时可用 +value;更新变量时先确认变量当前类型。
易错点:+= 遇到字符串会拼接;typeof null 的结果是 "object",这是 JS 的历史遗留;不要用 + 转数字时忽略字符串拼接风险。

小结 ​

本节回顾的核心是两条线:第一,转换前先问“转成谁”,再套 number/string/boolean 规则;第二,运算符表达式中先看操作数类型,尤其注意 +、==、+= 和逻辑运算符的返回值。后续写条件判断时,条件表达式最终也会落到真假判断上,所以假值列表必须熟记。

条件表达式:分支结构的“开关” ​

为什么需要:程序不能只会从上到下一条道走到黑,很多需求要根据条件决定执不执行某段代码,所以先要有一个“条件”。

怎么想:if 后面的小括号里放条件表达式,表达式最终会被当作布尔值使用:成立就是 true,不成立就是 false。不一定是直接写 true 或 false,写 56 * 7 这样的表达式也可以,结果不是 0,就相当于成立。

怎么做:

js
if (true) {
  console.log('条件成立');
}

易错点:小括号里要写条件表达式,不要写成让人误解的语句式写法;大括号里的代码要缩进,虽然不缩进不报错,但读代码时很难看出它属于分支结构。

单向分支:成立才执行,不成立就跳过 ​

为什么需要:有些逻辑只在满足条件时做一次,比如未成年人提示,成年人不需要提示。

怎么想:if (条件) { 语句 },条件成立执行大括号里的语句,不成立直接跳过,继续执行分支结构后面的代码。

怎么做:

js
console.log('语句1');
console.log('语句2');

if (true) {
  console.log('语句3');
  console.log('语句4');
}

console.log('语句5');
console.log('语句6');

把 true 改成 false,语句 3、4 不执行,1、2、5、6 照常执行。易错点:分号要用英文分号;分支外边的语句不受条件影响;大括号里写多少条语句都可以。

用 prompt 让条件“活”起来 ​

为什么需要:条件写死成 true 或 false,感受不到判断的意义,要让用户输入来决定条件。

怎么想:prompt 弹出输入框,把用户输入保存到变量里,再拿这个变量做判断。

怎么做:

js
let age = prompt('请输入年龄');
console.log(age, typeof age);

调试时会发现:即使用户输入纯数字,typeof 得到的仍是字符串。原因是程序提前不知道用户会输入什么,统一按字符串接收更合理。要参与大小比较,可以转成数字:

js
let age = +prompt('请输入年龄');
if (age < 18) {
  alert('未成年人请在家长陪同下观看');
}
alert('欢迎访问');

易错点:prompt 得到的是字符串;用 + 或 Number() 转数字;如果用户乱写,转数字可能得到 NaN,标准程序还应做合法性判断,这里先假设用户老老实实输入纯数字。

双向分支:两条路必须选一条 ​

为什么需要:有些需求不是“做或不做”,而是“做这个还是做那个”。

怎么想:if (条件) { ... } else { ... },条件成立走 if,不成立走 else,两者必执行其一。

怎么做:

js
let money = +prompt('请输入您的存款(元)');
if (money > 100000) {
  alert('这里有最新款的汽车,请付款');
} else {
  alert('电动车,请汇款');
}
alert('请到收银台');

易错点:else 后面不写条件;if 和 else 的大括号里都可以写多条语句;条件不成立时只执行 else,不会两边都执行。

三元运算符:简单双向分支的简写 ​

为什么需要:当双向分支每个分支只有一条简单语句时,用 if...else 显得啰嗦。

怎么想:条件 ? 表达式1 : 表达式2,条件成立取表达式 1 的值,否则取表达式 2 的值。

怎么做:

js
let money = +prompt('请输入您的存款(元)');
money > 100000 ? alert('最新款汽车,请付款') : alert('电瓶车,请汇款');

还可以直接组成表达式:

js
let msg = money > 100000 ? '最新款汽车' : '电瓶车';
alert(msg);

易错点:三元运算符的第二个、第三个操作数本质上要是表达式,每个分支只能放一条简单内容;如果每个大括号里要写很多条语句,三元运算符搞不定,还是得用 if...else。

多向分支:成绩判断的逐步优化 ​

为什么需要:成绩要分不及格、刚及格、中等、良好、优秀五种情况。

怎么想:先用单向分支写 5 个 if。能实现,但条件要写 >=60 && <70 这类组合,比较累;而且成绩 57 已经命中“不及格”后,后面几个分支还会继续判断。

改用双向分支嵌套,可以把下界省略:能进入 else,说明前面“小于 60”不成立,也就是已经大于等于 60,于是只写 <70 即可。它减少了重复判断,但嵌套层数多,可读性差。

最后用 else if 把嵌套拉平:

js
let score = +prompt('请输入您的成绩');

if (score < 60) {
  alert('您的成绩不及格');
} else if (score < 70) {
  alert('您的成绩刚及格');
} else if (score < 80) {
  alert('您的成绩中等');
} else if (score < 90) {
  alert('您的成绩良好');
} else {
  alert('您的成绩优秀');
}

易错点:区间边界要统一,60 到 70 指大于等于 60、小于 70;else if 后面的条件可以省略下界,因为前面的条件不成立才轮得到它;多层嵌套一定要缩进,否则代码很难读。

单向分支:条件成立才执行 ​

为什么需要:程序不能只会从上到下顺序执行,还要能根据条件决定“做不做”。单向分支适合“条件成立才执行,不成立就跳过”的场景。

怎么想:if 后的小括号里写条件表达式,最终按布尔值判断:成立执行大括号,不成立直接跳过,分支后面的语句照常执行。

怎么做:

js
console.log("语句1");
console.log("语句2");

if (true) {
  console.log("语句3");
  console.log("语句4");
}

console.log("语句5");
console.log("语句6");

把 true 改成 false,就只输出 1、2、5、6;写 56 * 7 也会因结果非 0 而成立。应用示例:

js
let age = prompt("请输入年龄");
if (age < 18) {
  alert("未成年人请在家长陪同下观看");
}
alert("欢迎访问");

输入 16 会提示未成年人,输入 67 则只显示欢迎。prompt 返回字符串,比较时会发生类型转换;若用户乱写,可能转成 NaN。

易错点:小括号里要写表达式,不要写成赋值语句;大括号内要缩进;条件外的语句不受分支影响;不要依赖用户一定输入纯数字。

双向分支:成立与不成立二选一 ​

为什么需要:有些场景不仅“成立时做事”,不成立时也要处理,这时用 if...else。

怎么想:条件成立执行 if 大括号,不成立执行 else 大括号,二者必执行其一。

怎么做:

js
console.log("语句1");
console.log("语句2");

if (false) {
  console.log("语句3");
  console.log("语句4");
} else {
  console.log("语句5");
  console.log("语句6");
}

应用:

js
let money = prompt("请输入您的存款(元)");
if (money > 100000) {
  alert("这里有最新款的汽车,请付款");
} else {
  alert("电动车,请汇款");
}
alert("请来收银台");

输入 67 走电动车,输入 20 万走汽车。

易错点:else 后不写条件;if 与 else 的大括号、缩进要清楚;空字符串、0 等转布尔时可能为 false。

三元运算符:简化简单二选一 ​

为什么需要:非常简单的二选一,用 if...else 显得啰嗦,可用三元运算符。

怎么想:条件 ? 表达式1 : 表达式2,条件成立取表达式1的值,否则取表达式2的值。

怎么做:

js
let money = prompt("请输入您的存款");
money > 100000
  ? alert("买车")
  : alert("买电瓶车");

还可直接写成:

js
money > 100000 ? "买车" : "买电瓶车";

易错点:三元运算符的两个分支只能写表达式,不能塞多条复杂语句;复杂双向分支仍应使用 if...else。

成绩判断:单向分支实现 ​

为什么需要:多区间判断是常见需求,例如按成绩输出不及格、刚及格、中等、良好、优秀。

怎么想:可以写 5 个独立的 if,每个条件用逻辑与限定区间。

怎么做:

js
let score = prompt("请输入您的成绩");
if (score < 60) alert("不及格");
if (score >= 60 && score < 70) alert("刚及格");
if (score >= 70 && score < 80) alert("中等");
if (score >= 80 && score < 90) alert("良好");
if (score >= 90) alert("优秀");

调试时输入 67 显示刚及格,23 显示不及格,99 显示优秀,81 显示良好,77 显示中等。

易错点:区间不能只写 <=69 而漏掉下界,否则会把 60 以下也纳入;缺点也明显:条件表达式复杂,而且即使已判断出不及格,后面几个 if 仍会继续判断。

成绩判断:双向分支嵌套实现 ​

为什么需要:利用 else 已排除前面条件的特点,可以简化后续条件,并在命中后不再判断后续分支。

怎么想:先判断 <60,否则说明已经 >=60,再在 else 里判断 <70,依次嵌套。

怎么做:

js
let score = prompt("请输入您的成绩");
if (score < 60) {
  alert("不及格");
} else {
  if (score < 70) {
    alert("刚及格");
  } else {
    if (score < 80) {
      alert("中等");
    } else {
      if (score < 90) {
        alert("良好");
      } else {
        alert("优秀");
      }
    }
  }
}

输入 12 显示不及格后,后续分支不再执行。

易错点:嵌套层数多,可读性差;必须严格缩进,否则逻辑容易看乱。

成绩判断:多向分支实现 ​

为什么需要:既要条件简单,又要命中后停止判断,还要可读性好,可用 else if。

怎么想:把“否则再判断”写成连续的 else if,最后用 else 兜底。

怎么做:

js
let score = prompt("请输入您的成绩");
if (score < 60) {
  alert("不及格");
} else if (score < 70) {
  alert("刚及格");
} else if (score < 80) {
  alert("中等");
} else if (score < 90) {
  alert("良好");
} else {
  alert("优秀");
}

这是该案例更优的写法:条件不复杂,执行到某个分支成立后,后续 else if 不再判断。

易错点:else if 要分开写清楚;最后 else 可省略但要根据需求决定;条件顺序要从小到大,避免区间被前面的条件截断。

课堂画面 ​

课堂画面 1

课堂画面 2

课堂画面 3

课堂画面 4

课堂画面 5

课堂画面 6

代码示例 ​

示例 1:单向分支 if(含用户输入应用) ​

html
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>单向分支</title>
</head>
<body>
  <script>
    // ---- 基础结构:条件为 true 才执行大括号里的语句 ----
    console.log('语句01');
    console.log('语句02');

    if (true) {          // 小括号里是“表达式”,会自动转成 boolean
      console.log('语句03');
      console.log('语句04');
    }

    console.log('语句05');   // 分支之外,永远执行
    console.log('语句06');

    // ---- 应用:根据用户输入的年龄做判断 ----
    var age = prompt('请输入年龄');      // 用户输入的内容,类型是 string
    console.log(age, typeof age);        // 逗号只是参数分隔符,不是运算符

    if (age < 18) {                      // 字符串会参与运算并自动转 number
      alert('未成年人请在家长陪同下观看');
    }

    console.log('欢迎访问');
  </script>
</body>
</html>

要点解释

  • if (true):小括号里要求是表达式,写 a = 100 这种语句会报错;true、false、56 * 7、变量、直接量都算表达式,最终按 Boolean 规则转成真假(0、NaN、空字符串、null、undefined 为假)。
  • 大括号里的语句必须缩进,语法不报错,但可读性极差。
  • prompt() 返回的永远是字符串(哪怕输入的是纯数字),所以后面参与 < 比较时才自动转 number;如果用户乱写字母,会转成 NaN,判断就不准了。
  • 单向分支条件不成立时直接跳过大括号,但 console.log('欢迎访问') 在分支之外,无论成不成立都会执行。

示例 2:双向分支 if…else 与三元运算符实现 ​

html
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>双向分支</title>
</head>
<body>
  <script>
    // ---- if…else 基础结构 ----
    console.log('语句01');
    console.log('语句02');

    if (true) {
      console.log('语句03');
      console.log('语句04');
    } else {
      console.log('语句05');
      console.log('语句06');
    }

    // ---- 应用:根据存款金额决定卖什么 ----
    var money = prompt('请输入您的存款(单位:元)');

    if (money > 100000) {
      alert('这里有最新款的汽车,请付款');
    } else {
      alert('电动车,请汇款');
    }

    alert('请到收银台');   // 分支之外的语句,一定会执行

    // ---- 用三元运算符实现同一个双向分支 ----
    var money2 = prompt('请输入您的存款(单位:元)');
    console.log(money2 > 100000 ? '最新款的汽车' : '电动车');
  </script>
</body>
</html>

要点解释

  • if…else:两个分支必执行其中一个,不像单向分支可能什么都不执行。
  • if 与 (、) 与 {、else 与 { 之间的空格写不写都不影响运行,写上是为了好看。
  • money 是字符串,money > 100000 时会自动转 number 再比较,所以转不转 Number() 结果一样(但用户乱写就会变 NaN)。
  • 三元运算符:条件 ? 表达式1 : 表达式2,第 2、3 个操作数只能是表达式,且只能各一条;示例里每个分支只有一条语句才勉强能用三元替代,分支里要写多条语句时三元运算符就搞不定了,所以实际开发绝大多数双向分支还是用 if…else。

示例 3:成绩判断——多向分支(if…else if…else) ​

html
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>成绩判断 - 多向分支</title>
</head>
<body>
  <script>
    var score = prompt('请输入您的成绩');

    if (score < 60) {
      alert('您的成绩不及格');
    } else if (score < 70) {        // 能走到这里,说明已经 >= 60
      alert('您的成绩刚及格');
    } else if (score < 80) {        // 能走到这里,说明已经 >= 70
      alert('您的成绩中等');
    } else if (score < 90) {        // 能走到这里,说明已经 >= 80
      alert('您的成绩良好');
    } else {                        // 前面条件全不成立,说明 >= 90
      alert('您的成绩优秀');
    }
  </script>
</body>
</html>

要点解释

  • else if 的两个关键字之间要有空格,不能写成 elseif;它不是把 if 套进 else 的大括号里,所以不会层层嵌套,可读性比双向分支嵌套高很多。
  • 每个 else if 里的条件只写上限即可:能执行到这一行,就证明前面的条件全都不成立,也就是已经 >= 60、>= 70……不用再重复写 score >= 60 &&。
  • 结论一旦得出,后面的分支就不会再判断(例如 50 分命中第一个分支,后面全跳过),这比写 5 个独立单向分支(每个条件都要用 && 拼接,且每次都要逐个判断)既省代码又省执行。
  • 最后的 else 可以不写,但写了就表示“前面条件都不成立”的兜底情况;本案例的假设是用户老老实实输入数字,如果乱写会得到 NaN,所有比较都为 false,会直接落进最后的 else。

常见错误 ​

  1. 现象:prompt() 拿到“18”后直接比较,边界结果偶尔不对。→ 原因:返回值始终是字符串,依赖隐式转换且未校验非法输入。→ 修法:先显式转数值并校验,如 const age = Number(prompt(...)); if (Number.isNaN(age)) { ... }。
  2. 现象:成绩判断写了 5 个独立 if,输入 50 后仍继续判断后面区间。→ 原因:把互斥区间写成多个单分支,条件彼此独立。→ 修法:互斥区间优先改 else if,命中后不再继续判断。
  3. 现象:else if 链里每个条件都重复写“大于等于上一档”。→ 原因:没有利用前面条件不成立这一隐含前提。→ 修法:进入后续分支时只保留上界判断,如 else if (score < 70)。
  4. 现象:双向分支嵌套多层后代码难读,改条件时容易改错层级。→ 原因:用嵌套表达多区间,缩进和括号层级过深。→ 修法:多区间改用 else if;保留嵌套时必须统一缩进,并先梳理区间边界。
  5. 现象:用三元运算符改写双分支时写不进多条语句或复杂逻辑。→ 原因:三元运算符的两个分支只能放表达式,不适合语句块。→ 修法:仅用于简单二选一取值;涉及多条语句、告警、流程控制时改用 if...else。
  6. 现象:if (a = 100) 不报错但条件行为异常。→ 原因:把比较写成了赋值表达式。→ 修法:条件中避免赋值;需要比较时用 ===,并借助编辑器/ ESLint 检查。

练习 ​

  1. 分别用“多个单分支”“双向分支嵌套”“else if 多分支”实现成绩判断,记录三版代码各自在输入 50 时会执行多少次条件判断,并说明哪版最适合维护。
  2. 改造“存款买车/买电瓶车”案例:增加非法输入处理,用户输入空串、字母、负数时给出提示,不进入金额比较。
  3. 用三元运算符实现一个简单二选一提示,再写一个含两条语句的双分支版本,对比后说明三元运算符的适用边界。
  4. 为成绩判断设计一组测试用例,至少覆盖 59、60、69、70、89、90、100、非数字输入,并逐项写出预期档位。

原视频对照 ​

#视频时长
1单向分析14:20
2双向分支05:46
3三元运算符实现双向分支04:38
4成绩判断-使用单向分支实现08:15
5成绩判断-使用双向分支实现05:45
6成绩判断-多向分支实现04:41

小结 ​

  1. 互斥区间优先用 else if,不要用多个独立 if 反复判断。
  2. 单分支适合“满足才做”的附加动作,双分支适合明确二选一。
  3. 三元运算符只适合简单表达式取值,不要硬塞复杂流程。
  4. prompt() 的结果按字符串处理,数值比较前要显式转换并校验。
  5. 多分支的关键不是少写代码,而是利用“前面不成立”的前提简化条件。
  6. 嵌套不是不能用,但层级一深就要优先考虑改写成 else if。
  7. 边界值和非法输入必须进入测试清单,不能只测中间值。