Skip to content

案例-字符串拼接与案例-阶梯水价(Day4 1/3) ​

本页对应 Day04_JavaScript,共 7 段视频,约 1 小时 1 分。

学习目标 ​

  1. 能根据给定代码判断 if、switch case 及嵌套分支的执行流程和最终变量值,并说明 break 缺失时的影响。
  2. 能使用 + 完成字符串与变量拼接,正确区分变量写在引号内外,并输出指定格式的个人信息。
  3. 能使用 if-else if-else 编写阶梯水价程序,按 220、300 分档计算费用,并使用 isNaN 校验用户输入。
  4. 能推导并写出闰年判断表达式,综合 %4、%100、%400 和逻辑运算符,对指定年份输出闰年或平年。
  5. 能使用 while 循环定义循环变量、循环条件和更新表达式,完成指定次数、指定范围、倒序及偶数输出,并避免死循环。
  6. 能在 while 循环中正确初始化累加变量和累乘变量,完成 100 以内数字求和、10 以内奇数求积,并说明循环结束后循环变量的值。

知识点 ​

本节说明与分支回顾 ​

本节笔记未显示图片,故不插入图片;转写稿中的代码按原意整理保留。先纠正同音字:where 应为 while,Lif 应为 else if,不瑞应为 break,艾斯应为 else,实纪年应为世纪年,南本应为 number。

分支结构要掌握:单分支、双分支、多分支(else if 与 switch case)、嵌套。为什么需要:不同场景选择不同结构。怎么想:判等优先 switch case,范围或复杂条件用 else if;case 下要缩进,必要时写 break。易错点:漏 break 会穿透;条件表达式结果要按 true/false 判断。

练习一:

js
let a = 10;
if (110 && 'hello' * 1) {
  a++;
}
console.log(a); // 10

推导:'hello' * 1 得 NaN,逻辑与第二边不成立,整体不成立,a++ 不执行,所以仍是 10。易错点:不要被左边 110 迷惑,逻辑与要求两边都成立。

练习二:

js
let a = 20;
switch (a) {
  case 10: a += 10;
  case 20: a += 20;
  case 30: a += 30;
  case 40: a += 100;
}
console.log(a); // 170

从 case 20 进入,未写 break,继续执行 +20、+30、+100,即 20+20+30+100=170。易错点:switch 的“穿透”是调试重点。

字符串拼接案例 ​

为什么需要:开发中经常把变量嵌入提示文本。怎么想:先写完整大字符串,把要替换的位置留标记,再逐段用 + 拼变量。怎么做:

js
let name = '高晓乐';
let gender = '男';
let hometown = '山西';
let hobby = '吃醋';
let money = 0.25;
let message = '我的名字叫' + name + ',性别' + gender +
  ',我来自' + hometown + ',我的爱好是' + hobby +
  ',期望薪资是' + money + 'K';
console.log(message);

易错点:变量名必须写在引号外;拼接符两边空格可加可不加,变量多时要注意引号闭合。转写中“0.25K”可写成 .25K,但建议保留 0 提高可读性。

阶梯水价案例 ​

为什么需要:分段计费不能简单“总用量乘单价”。怎么想:先判断档位,再分段累加。怎么做:

js
let vol = +prompt('请输入您的用水量(立方米)');
let total;
if (vol <= 220) {
  total = 4.05 * vol;
} else if (vol <= 300) {
  total = 220 * 4.05 + (vol - 220) * 5.8;
} else {
  total = 220 * 4.05 + 80 * 5.8 + (vol - 300) * 8.79;
}
alert('您需要缴纳水费:' + total);

推导:进入 else if (vol <= 300) 时,已经隐含 vol > 220,所以超出部分用 vol - 220。易错点:忘记把输入转数字;忽略分段;金额可能出现小数精度问题,输出时可考虑保留两位。也可用 isNaN 先校验输入。

闰年判断案例 ​

为什么需要:闰年规则不是简单“能被 4 整除”。怎么想:先分世纪年与非世纪年。非世纪年:不能被 100 整除且能被 4 整除;世纪年:能被 400 整除。怎么做:

js
let year = +prompt('请输入年份');
if ((year % 100 !== 0 && year % 4 === 0) || year % 400 === 0) {
  console.log(year + '是闰年');
} else {
  console.log(year + '是平年');
}

推导:year % 100 !== 0 排除世纪年,year % 4 === 0 判非世纪年闰年;year % 400 === 0 判世纪年闰年,二者用 || 合并。易错点:漏掉“不能被 100 整除”,会把 1900 误判为闰年;括号虽不改变优先级,但能提高可读性。

while 循环基础与调试 ​

为什么需要:重复执行同一组语句。怎么想:循环条件不能永远成立,循环变量要逐渐趋向不成立。怎么做:

js
let number = 0;
while (number < 10) {
  console.log('高晓乐第' + number + '天吃了' + number + '个韭菜馅的包子');
  number++;
}
console.log(number); // 10

调试:若写 while (true) 会死循环;忘记 number++ 也会死循环。循环结束后 number 是让条件不成立的值,所以是 10。易错点:自增要放在循环体内;输出 0 到 9 共 10 次。

while 循环练习 ​

输出 7 到 15:

js
let i = 7;
while (i <= 15) {
  console.log(i);
  i++;
}
console.log(i); // 16

倒序输出 56 到 43:

js
let i = 56;
while (i >= 43) {
  console.log(i);
  i--;
}
console.log(i); // 42

易错点:倒序要递减;结束值定格在让条件不成立的位置。

输出 10 以内偶数,两种写法:

js
let i = 0;
while (i <= 10) {
  if (i % 2 === 0) console.log(i);
  i++;
}
js
let i = 0;
while (i <= 10) {
  console.log(i);
  i += 2;
}

第二种结束后 i 为 12。易错点:i += 2 不能写成 i++;0 是偶数。

100 以内数字和:

js
let sum = 0;
let i = 1;
while (i <= 100) {
  sum += i;
  i++;
}
console.log(sum); // 5050

10 以内奇数乘积:

js
let res = 1;
let i = 1;
while (i < 10) {
  res *= i;
  i += 2;
}
console.log(res); // 945

易错点:求和初始值用 0,求乘积初始值用 1;忘记 i++ 或 i += 2 会死循环。

回顾清单与学习目标 ​

本节是对分支结构的阶段回顾,重点不是新增语法,而是把几种写法放回具体场景里:什么时候用 if,什么时候用 if...else,什么时候用 else if,什么时候用 switch case,以及大括号里还能不能继续嵌套。先保留本节笔记中的清单:

text
1. 单向分支
2. 双向分支
3. 多向分支 else if
4. 多向分支 switch case
5. 嵌套

为什么需要回顾:分支结构语法不难,但真实题目里“条件有没有成立”“该进哪个分支”“要不要 break”最容易出错。怎么想:先判断需求是“做不做”“二选一”“多区间判断”还是“等值判断”。怎么做:按清单逐个对照。易错点:不要把 else if 和 switch case 当成互相替代;也不要以为写了分支就一定会执行。

单向分支 ​

为什么需要:有些逻辑只在条件成立时做一件事,不成立就什么也不做,这时用单向 if 最直接。怎么想:先问“条件不成立时要不要有替代动作?”如果不需要,就只写 if。怎么做:写条件表达式,条件成立执行大括号里的语句;不成立就跳过。转写稿中的第一道回顾题就考这个点:代码里有一个单向分支,后面输出变量值。反复强调“核心在于这条语句有没有执行”,因为只有条件成立,变量才会自增 1;条件不成立,变量保持原值。现场推导时,条件表达式虽然带逻辑与,看起来复杂,但最终不成立,所以自增语句没有执行,答案仍是 10。易错点:看到 if 就以为一定会进去;忽略复杂条件最终为假;把“输出变量”误当成“变量一定被改过”。

双向分支 ​

为什么需要:当条件成立做 A,不成立做 B,就需要 if...else。怎么想:把需求翻译成“要么……要么……”,两条路必走一条。怎么做:if 后写成立时的语句,else 后写不成立时的语句。易错点:else 后面不要再写条件;两个分支只会执行一个;大括号内语句要缩进,方便看出归属。转写稿中用“区别能想到吧”提醒:单向分支可能一次都不执行,双向分支在二选一场景中必定进入其中一个分支。

多向分支:else if ​

为什么需要:当条件不止两个,而且可能是区间判断、复合条件判断时,else if 更合适。怎么想:从上到下依次判断,一旦某个条件成立,就执行对应分支,后面的 else if 不再判断。怎么做:先写第一个 if,再写多个 else if,最后可用 else 兜底。易错点:条件顺序会影响结果;能进入后面的 else if,往往说明前面的条件已经不成立。转写稿提到 else if “各种场景是不是都合适”,而 switch case 更适合判等;所以复杂条件、区间判断优先考虑 else if。

多向分支:switch case ​

为什么需要:当需求是“表达式等于某个值就做什么,等于另一个值就做什么”,switch case 更清晰。怎么想:先看是不是等值判断;是等值判断就优先 switch case,它搞不定的复杂条件再用 else if。怎么做:用表达式匹配 case,每个 case 后写执行语句,必要时写 break。转写稿第二道题:变量 A 的初值是 20,从 case 20 进入;但每个 case 后没有写 break,所以不会停,会继续往下贯穿执行,先加 20,再加 30,再加 100,即 20 + 20 + 30 + 100 = 170。易错点:漏写 break 会“贯穿”;case 下要注意缩进;switch case 适合判等,不要硬拿它处理复杂区间。

嵌套 ​

为什么需要:真实逻辑常常是“分支里还有分支”。怎么想:先判断外层大条件,再在某个分支内部继续判断小条件。怎么做:if...else 的大括号中可以再套一层 if 或 else if;switch case 的 case 下面也可以继续写逻辑。转写稿强调“大括号中是不是可以再套一层”,甚至 switch case 的 case 下面也可以再套,但 case 下面一定要注意缩进。易错点:嵌套层级太多会降低可读性;缩进混乱会导致自己看错归属;不要为了嵌套而嵌套,能平铺的条件可优先平铺。

小结 ​

本节回顾的关键是“按场景选结构”:单向 if 管“做不做”,if...else 管“二选一”,else if 管多条件,switch case 管等值匹配,嵌套用于分支里再分支。转写稿里两道题分别提醒了两个高频错误:条件不成立时语句不会执行,所以变量可能保持原值;switch case 漏写 break 会继续往下执行。分支语法记得少,但练习要多,重点是把条件、执行路径和变量变化一步步推清楚。

课堂画面 ​

课堂画面 1

课堂画面 2

课堂画面 3

课堂画面 4

课堂画面 5

课堂画面 6

代码示例 ​

示例一:字符串拼接(“+”连接符练习) ​

html
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>字符串拼接</title>
</head>
<body>
<script>
  // 1. 先定义好 5 个变量
  var name = '高晓乐';      // 姓名
  var gender = '男';        // 性别
  var hometown = '山西';    // 家乡
  var hobby = '吃醋';       // 爱好
  var money = .25;          // 期望薪资,单位 K(0.25 的 0 可以省略)

  // 2. 思路:先写出完整的大字符串,需要拼变量的地方先用 X 占位,
  //    再把 X 删掉,换成 引号结束 + 变量 + 引号开始
  var message = '我的名字叫' + name
              + ',性别' + gender
              + ',我来自' + hometown
              + ',我的业余爱好是' + hobby
              + ',我的期望薪资是' + money + 'K';

  // 3. 输出看看结果
  console.log(message);
</script>
</body>
</html>

要点解释:

  • '...' + name + '...':拼接时变量名必须写在引号外面,写进引号里就变成普通文字了(转写稿原话:“写引号里边就完犊子了”)。
  • 加号两边的空格加不加都行,语法上没区别,加空格只是为了好看、好读。
  • money = .25:JS 里 0.25 的小数点前的 0 可以省略。
  • 拼接变量多时,建议先写完整字符串、再用“X”占位逐个替换,比边写边拼更不容易出错。

示例二:阶梯水价(多向分支 else if) ​

html
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>阶梯水价</title>
</head>
<body>
<script>
  // 1. 获取用户输入(prompt 得到的是字符串)
  var val = prompt('请输入您的用水量(单位:立方米)');

  // 2. 先判断用户输入格式对不对,不是数字就提示
  if (isNaN(val)) {
    alert('请输入正确的格式,必须是数字!');
  } else {
    // 3. 转成数字再参与计算
    val = parseFloat(val);

    var total; // 记录总价
    if (val <= 220) {
      // 第一档:全部按 4.05 算
      total = 4.05 * val;
    } else if (val <= 300) {
      // 第二档:220 的部分按 4.05,超出 220 的部分按 5.8
      total = 220 * 4.05 + (val - 220) * 5.8;
    } else {
      // 第三档:220 部分 + 220~300 这 80 的部分 + 300 以上的部分
      total = 220 * 4.05 + 80 * 5.8 + (val - 300) * 8.79;
    }

    alert('您需要缴纳的水费是:' + total);
  }
</script>
</body>
</html>

要点解释:

  • else if (val <= 300) 里不用再判断“大于 220”:能走到这一行,说明前面的 val <= 220 已经不成立了,天然就是大于 220 的。
  • 三个分支互斥,一次只会执行一个,所以 total 不会被重复赋值。
  • isNaN(val) 为 true 说明输入的不是数字(比如输入 hello),要先拦掉;把后续判断放进 else 里,代码更严谨。
  • 小数相乘出现很长的小数位是正常现象(浮点精度问题),做金额输出时一般保留两位。
  • 阶梯计算套路:每档只算超出部分,220 * 4.05 + (val - 220) * 5.8,不要整段乘高价。

示例三:while 循环三个练习(偶数 / 求和 / 求积) ​

html
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>while 循环</title>
</head>
<body>
<script>
  // 需求 1:输出 10 以内所有偶数(含 0 和 10)
  var i = 0;
  while (i <= 10) {
    console.log(i); // 0 2 4 6 8 10
    i += 2;         // 每次加 2,让条件逐渐趋向不成立
  }
  console.log('循环结束后 i = ' + i); // 12

  // 需求 2:计算 100 以内所有数字的和(含 100)
  var sum = 0;   // 求和的初始值写 0
  var j = 1;
  while (j <= 100) {
    sum += j;    // 相当于 sum = sum + j
    j++;         // 千万别忘,忘了就是死循环
  }
  console.log('1~100 的和 = ' + sum); // 5050
  console.log('循环结束后 j = ' + j); // 101

  // 需求 3:计算 10 以内所有奇数的乘积(1*3*5*7*9)
  var result = 1; // 求积的初始值必须是 1,写 0 就永远是 0
  var k = 1;
  while (k < 10) {
    result *= k;  // 相当于 result = result * k
    k += 2;       // 每次加 2,正好跳过偶数
  }
  console.log('10 以内奇数的乘积 = ' + result); // 945
  console.log('循环结束后 k = ' + k);           // 11
</script>
</body>
</html>

要点解释:

  • 一个“正儿八经的循环”必须满足两点:循环条件不能永远成立,且每循环一次条件要越来越趋向不成立(转写稿里 while (true) 直接演示了浏览器死机)。
  • 循环变量的自增(i++、i += 2)要写在循环体里面、循环体外面都行但不能漏;写 while (i <= 10) 却忘了 i++,就是典型死循环。
  • 输出偶数有两种写法:一是 i += 2 直接步进(代码更简洁),二是在循环体里套一个 if (i % 2 == 0) 单项分支,两种都能得到 0 2 4 6 8 10。
  • 求和初始值写 0(加它没影响),求积初始值必须写 1(乘 0 结果永远是 0)——这是求积最容易踩的坑。
  • 循环结束后,循环变量的值定格在“让条件不成立的那个值”:i 是 12、j 是 101、k 是 11,而不是最后一个执行循环体的值。

常见错误 ​

  1. switch 分支“穿透”,结果比预期大很多

    • 现象:输入 20,进入 case 20 后把后面所有分支都执行了一遍,得到 170 之类的结果。
    • 原因:每个 case 末尾漏写 break,匹配成功后不会自动跳出,会继续往下执行。
    • 修法:每个 case 处理完立即补 break;确实要故意穿透时,加注释说明意图,避免被当成 bug。
  2. while 条件永远成立,浏览器卡死

    • 现象:页面直接卡住,控制台刷屏,只能结束任务。
    • 原因:循环条件写成 true,或循环体内忘了让循环变量变化(漏写 i++)。
    • 修法:循环前先想清楚“什么条件下停”,循环体内必须让条件逐步趋向不成立;调试时先跑小次数。
  3. 循环结束后循环变量的值判断错

    • 现象:认为 i <= 10 结束后 i 是 10,实际是 11;i += 2 输出 0~10 后认为 i 是 10,实际是 12。
    • 原因:忽略“最后一次进入循环体后还会再执行一次自增”,变量定格在“让条件第一次不成立”的那个值。
    • 修法:判断结束值一律按“最后一次成立的值 + 一步变化量”推演;需要精确值时在循环外单独记录。
  4. 字符串拼接把变量写进引号里

    • 现象:页面直接输出 我的名字叫name,而不是变量的值。
    • 原因:把变量名写在了字符串字面量内部,它只是普通文本。
    • 修法:变量必须放在引号外,用 + 连接;拼接较多时先写好整句模板,再用“断开引号 + 变量 + 重新开引号”的方式逐段替换。
  5. 累加/累乘的初始值给错

    • 现象:求和结果总是 0,或求积结果永远是 0。
    • 原因:求和变量初始值给了 1,求积变量初始值给了 0。
    • 修法:累加初始值用 0,累乘初始值用 1;写之前先问自己“这个初始值参与运算后会不会污染结果”。
  6. 阶梯计费只乘当前单价,漏掉分段

    • 现象:用水 250 立方米时直接 250 * 5.8,费用明显偏高。
    • 原因:把阶梯价当成“整段按最高档计价”,没有分段累加。
    • 修法:先算满额档位部分,再算超出部分;写完后用临界值(220、300)各测一次。
  7. 闰年条件漏掉“世纪年”分支

    • 现象:1900、2100 被判成闰年。
    • 原因:只写了“能被 4 整除”,没区分整百年份需要被 400 整除。
    • 修法:先用 year % 100 === 0 判断是否世纪年,再分别套用两套条件;最后用 1900、2000、2024、2100 四个值回归测试。
  8. prompt 拿到的是字符串就直接比较/计算

    • 现象:输入 "100" 与数字比较或相加时结果诡异,或用户乱输入导致条件全部不成立。
    • 原因:prompt 返回值是字符串,隐式转换不可控。
    • 修法:先 Number() 转换,再用 isNaN() 校验格式;非法输入走单独提示分支,不要混进业务计算。

练习 ​

  1. 分支穿透排查:给出一段 switch 代码(多个 case 无 break),先手写推演输出结果,再上机验证;然后补全 break,对比两次结果差异,写出“穿透”发生的位置。

  2. 阶梯水价边界测试:实现阶梯水价后,分别输入 0、220、220.01、300、300.01、1000,记录每档费用明细;再输入 abc、空字符串,验证非法输入是否被拦截。

  3. 闰年判断回归表:写一个判断闰年的表达式,用 1900、2000、2024、2100、2200、2023 六个数逐一测试,把每个年份的“世纪年/非世纪年”和判断结果列成表格,检查是否全部正确。

  4. 循环改错:给出三段有问题的 while 代码(死循环、初始值给错、自增写在 if 内部导致漏加),找出每段的问题并改正,说明“循环变量必须每次都被改变”的理由。

  5. 一题多解:输出 0~10 内所有偶数,用两种写法实现(循环体内 if 判断、循环变量每次 += 2),比较两种写法循环结束后的变量值分别是多少,并说明为什么不同。

原视频对照 ​

#视频时长
1回顾06:37
2案例-字符串拼接06:02
3案例-阶梯水价07:52
4案例-闰年判断12:41
5while循环0111:14
6while循环0202:44
7while循环0314:15

小结 ​

  1. 分支的坑集中在“该跳不跳”和“条件写漏”:switch 记得 break,if 记得覆盖所有区间和边界。
  2. 区间判断要养成“先想边界值”的习惯,220、300、整百年份这类临界点必须单独测。
  3. 循环三要素缺一不可:初始值、终止条件、变量变化;少任何一个都可能变成死循环或零次循环。
  4. 循环结束后变量的值永远是“让条件第一次不成立的那个值”,不要凭直觉猜。
  5. 累加初始值 0、累乘初始值 1,这是必须条件反射的常识。
  6. 字符串拼接时变量一定在引号外,拼接段数多时先写模板再替换,能显著降低出错率。
  7. prompt 的返回值默认是字符串,进入计算前先转换、先校验,非法输入走独立分支。
  8. 这类语法点“记得少、练得多”,写完必须跑一遍边界数据,靠肉眼检查代码是最容易漏坑的方式。