主题
1-8分支+循环综合案例
本页对应 第一章JavaScript基础,共 2 段视频,约 17 分钟。
学习目标
- 能使用
while (true)编写循环菜单,并通过prompt反复接收用户操作输入。 - 能将
prompt获取的字符串转换为数字类型,确保比较和运算时数据类型一致。 - 能使用
if / else if多分支语句实现取款、存款、查看余额和退出四类操作。 - 能声明并维护
money变量记录银行卡余额,正确完成金额累加、扣减与重新赋值。 - 能使用
break在用户输入退出指令时结束无限循环,避免产生死循环。 - 能使用赋值运算符简化余额计算,并在程序结束后输出最终银行卡余额。
知识点
综合案例总览
本节做两个综合案例:手风琴效果、根据数据渲染柱形图。它们共同的核心是:准备数据 → 循环遍历 → 拼接字符串 → 放入页面容器渲染。
为什么需要?因为页面中重复结构很多,手写会冗余且难维护;数据一变,结构就应跟着变。怎么想?先问“重复的部分是什么”,再问“数据放在哪里”,最后用循环把数据塞进模板字符串。怎么做?声明空字符串 str,循环里用 += 拼接,最后用 document.write 或容器渲染。易错点:str 要声明在循环外;模板字符串要用反引号;${} 中写变量;拼接字符串时的 + 是拼接,不是数值加法。转写稿里反复强调“prompt 取回的是字符串、类型要统一、循环要有退出条件”,这些调试意识同样适用于本节:先检查数据类型,再检查循环边界,最后检查拼接结果。
手风琴效果:用循环拼接结构

为什么需要?手风琴有 7 个重复的 <div><img></div>,手写容易漏、改路径麻烦。怎么想?把 7 张图片路径放进数组,用循环生成相同结构。怎么做?① 声明空字符串 let str = '';② 循环中 str += `<div><img src="\${arr[i]}" alt=""></div>`;③ 把 str 放进 .box 容器。易错点:str 必须写在循环外,否则每次都被清空;模板字符串必须用反引号;图片路径要用 \${arr[i]};document.write 会直接写页面,适合当前空页面案例。转写稿提到“加号最容易出问题”,这里要区分:数值相加要转数字,字符串拼接则正是用 +。
手风琴完整代码
js
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<style>
.box {
display: flex;
overflow: hidden;
width: 1120px;
height: 260px;
margin: 50px auto;
}
.box>div {
width: 120px;
border: 1px solid #fff;
transition: all 0.5s;
}
.box>div:hover {
width: 400px;
}
</style>
</head>
<body>
<!-- <div class="box">
<div><img src="./images/1.jpg" alt=""></div>
<div><img src="./images/2.jpg" alt=""></div>
<div><img src="./images/3.jpg" alt=""></div>
<div><img src="./images/4.jpg" alt=""></div>
<div><img src="./images/5.jpg" alt=""></div>
<div><img src="./images/6.jpg" alt=""></div>
<div><img src="./images/7.jpg" alt=""></div>
</div> -->
<script>
let arr = [
'./images/1.jpg',
'./images/2.jpg',
'./images/3.jpg',
'./images/4.jpg',
'./images/5.jpg',
'./images/6.jpg',
'./images/7.jpg',
]
// 1. 声明一个空的字符串变量 str
let str = ''
// 2. 利用for循环拼接字符串 +=
for (let i = 0; i < arr.length; i++) {
// console.log(arr[i])
str += `
<div><img src="${arr[i]}" alt=""></div>
`
}
console.log(str)
// 3. 把拼接的字符串放入 box盒子里面
document.write(`
<div class="box">
${str}
</div>
`)
</script>
</body>
</html>柱形图:先收集数据,再按数据渲染

为什么需要?柱子的高度由用户输入的季度数据决定,不能写死。怎么想?先输入 4 次并存进数组,再遍历数组生成 4 个柱子。怎么做?① 声明空数组 arr;② 用 for (let i = 1; i <= 4; i++) 弹出 prompt,用 +prompt(...) 转数字后 push;③ 声明空字符串 str;④ 遍历 arr,拼接 <div style="height: \${arr[i]}px;" title="第\${i + 1}季度-\${arr[i]}万">...;⑤ 用 document.write 把 .box 和 str 写入页面。易错点:prompt 返回字符串,必须用 + 或 Number() 转数字;渲染时索引 i 从 0 开始,所以季度文字用 i + 1;高度要带 px;模板字符串别漏反引号。转写稿中“先准备金额变量,再在循环里做加减”的思路,对应到这里就是“先准备数组和字符串容器,再循环生成结构”。
柱形图完整代码
js
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<style>
* {
margin: 0;
padding: 0;
}
body {
background-color: #0c143d;
}
.box {
display: flex;
justify-content: space-around;
align-items: flex-end;
width: 800px;
min-height: 300px;
border-left: 1px solid #4b578f;
border-bottom: 1px solid #4b578f;
margin: 0 auto;
padding-top: 50px;
text-align: center;
color: #9799ab;
}
.box>div {
position: relative;
display: flex;
flex-direction: column;
justify-content: space-between;
width: 40px;
height: 0;
background: linear-gradient(#3c99ff, #4489d0, #2283e4);
cursor: pointer;
border-radius: 8px 8px 0 0;
transition: all .2s;
}
.box>div:hover {
animation: bg .5s alternate infinite;
}
@keyframes bg {
to {
box-shadow: 0 5px 29px rgb(53 111 226 / 88%);
background: linear-gradient(#3c99ff, #68aff6, #2283e4);
}
}
.box>div::after {
content: '';
position: absolute;
bottom: 0;
left: 50%;
width: 2px;
height: 10px;
background-color: #4b578f;
transform: translate(-50%, 100%);
}
.box div span {
width: 60px;
margin: -30px 0 -5px -6px;
}
.box div h4 {
width: 70px;
margin: 0 0 -35px -10px;
}
.title {
margin-top: 50px;
text-align: center;
color: #9799ab;
}
</style>
</head>
<body>
<h3 class="title">2099年季度销售数额(单位万)</h3>
<!-- <div class="box">
<div style="height: 123px;" title="第1季度-123万">
<span>123万</span>
<h4>第1季度</h4>
</div>
<div style="height: 156px;" title="第2季度-156万">
<span>156万</span>
<h4>第2季度</h4>
</div>
<div style="height: 120px;" title="第3季度-120万">
<span>120万</span>
<h4>第3季度</h4>
</div>
<div style="height: 210px;" title="第4季度-210万">
<span>210万</span>
<h4>第4季度</h4>
</div>
</div> -->
<script>
// 功能1: 用户输入4次,并且把数据存放到数组里面
// 1.1 声明一个空的数组
let arr = []
// 1.2 利用循环的形式让用户输入4次,并且把数据追加给数组
for (let i = 1; i <= 4; i++) {
let num = +prompt(`请您输入第${i}季度的销售额`)
arr.push(num)
}
console.log(arr)
// 功能2:根据数组生成柱形图
// 2.1 声明一个空的字符串 str
let str = ''
// 2.2 利用循环拼接字符串,生成多个柱子
for (let i = 0; i < arr.length; i++) {
str += `
<div style="height: ${arr[i]}px;" title="第${i + 1}季度-${arr[i]}万">
<span>${arr[i]}万</span>
<h4>第${i + 1}季度</h4>
</div>
`
}
console.log(str)
// 2.3 把生成的柱子放到box盒子里面进行渲染
document.write(`
<div class="box">
${str}
</div>
`)
</script>
</body>
</html>调试与检查清单
转写稿里出现的同音字要纠正:well 是 while,prot 是 prompt,复制运算符 是“赋值运算符”,简等/甲等 是“减等/加等”,ca是S 是 Ctrl+S。本节调试可照这个顺序:先用 console.log(str) 看拼接结果;再检查 prompt 数据是否转成数字;再检查模板字符串是否用反引号;最后检查循环外变量是否被误放循环内。两个案例都不是无限循环,但“循环要有明确边界、变量要在正确作用域”同样关键。
小结
手风琴案例练“数组 + 循环拼接 + 容器渲染”;柱形图案例练“先收集数据,再按数据生成结构”。记住三步:空字符串/空数组先准备,循环里 += 或 push,最后统一渲染。检查时优先看类型、模板字符串和作用域。
先看问题:为什么要学排序
数组里的数据经常需要“按大小排好”,比如成绩排名、价格从低到高、取最大值最小值。笔记先讲内置方法 sort(),再讲选择排序,是为了让你既会“用工具”,也理解“排序算法大概怎么想”。转写稿里反复强调调试时要先分析流程、再验证结果;排序同样要这样:先看默认结果对不对,再决定是否传比较函数。
数组排序 sort:为什么需要 → 怎么想 → 怎么做 → 易错点
为什么需要:手写排序麻烦,数组.sort() 可以直接排序,并且会修改原数组。
怎么想:先记住默认 sort() 不一定按数字大小排,而是容易按字符串规则比较;要按数值升序/降序,需要传入比较函数。比较函数返回 a - b 表示升序,返回 b - a 表示降序。
怎么做:保留笔记代码如下。
javascript
<script>
// 数组排序 数组.sort() 修改原数组
let arr = [88, 78, 100, 34, 99]
// arr.sort()
// console.log(arr) // [100, 34, 78, 88, 99]
// 1. 升序排序
// arr.sort(function (a, b) {
// return a - b
// })
// console.log(arr) // [34, 78, 88, 99, 100]
// 2. 降序排序
arr.sort(function (a, b) {
return b - a
})
console.log(arr) // [100, 99, 88, 78, 34]
// 3. 获取数组最大值和最小值
document.write(`数组的最大值:${arr[0]}`)
document.write(`数组的最小值:${arr[arr.length - 1]}`)
</script>易错点:arr.sort() 不传比较函数时,100 可能排在 34 前面,因为默认不是按数值减法比较;比较函数要 return a - b,不要写成 return a > b;sort() 会改原数组;排序后取最值要注意当前是升序还是降序。
选择排序:为什么需要 → 怎么想 → 怎么做 → 易错点
为什么需要:理解排序算法的基本过程,训练循环嵌套、索引交换和边界控制。算法可视化网站地址:https://visualgo.net/zh/sorting 。
怎么想:从第一个位置开始,假设它是最小值索引 minIndex,然后与后面所有元素比较,发现更小的就把 minIndex 改成那个元素的索引;一轮结束后,如果 minIndex 不在当前起点 i,就交换。每一轮确定一个相对最小值。
怎么做:保留笔记代码如下。
javascript
<script>
// 选择排序算法
let arr = [4, 2, 5, 1, 3]
// 1 [1, 2, 5, 4, 3]
// 2 [1, 2, 5, 4, 3]
// 3 [1, 2, 3, 4, 5]
// 4 [1, 2, 3, 4, 5]
// 1. 外层循环控制是几轮能够比较出来
for (let i = 0; i < arr.length - 1; i++) {
// 最小值的索引号
let minIndex = i
// 2. 里层循环来查找最小值,并且记录最小值的索引号
for (let j = i + 1; j < arr.length; j++) {
if (arr[j] < arr[minIndex]) {
minIndex = j
}
}
// 3. 交换变量
if (minIndex !== i) {
let temp = arr[minIndex]
arr[minIndex] = arr[i]
arr[i] = temp
}
}
console.log(arr)
</script>易错点:外层只跑 arr.length - 1 轮;minIndex 每轮要重置为 i;内层从 i + 1 开始;交换前判断 minIndex !== i;交换要借助 temp,不要直接覆盖。调试时可以像转写稿里强调的那样,先确认数据类型和条件是否一致,再打印每轮 arr 观察变化;转写稿中的“well、pro、预算符”应纠正为 while、prompt、运算符,这种“先定位类型与条件”的调试意识同样适用于排序。
课件图示

代码示例
示例一:手风琴效果(循环拼接字符串 + document.write 渲染)
js
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<style>
.box {
display: flex;
overflow: hidden;
width: 1120px;
height: 260px;
margin: 50px auto;
}
.box>div {
width: 120px;
border: 1px solid #fff;
transition: all 0.5s;
}
.box>div:hover {
width: 400px;
}
</style>
</head>
<body>
<script>
let arr = [
'./images/1.jpg',
'./images/2.jpg',
'./images/3.jpg',
'./images/4.jpg',
'./images/5.jpg',
'./images/6.jpg',
'./images/7.jpg',
]
// 1. 声明一个空的字符串变量 str
let str = ''
// 2. 利用for循环拼接字符串 +=
for (let i = 0; i < arr.length; i++) {
// console.log(arr[i])
str += `
<div><img src="${arr[i]}" alt=""></div>
`
}
console.log(str)
// 3. 把拼接的字符串放入 box盒子里面
document.write(`
<div class="box">
${str}
</div>
`)
</script>
</body>
</html>关键行与易错点
let str = ''是“累加和”思想的字符串版本:先准备空字符串,再在循环里+=累加,循环结束后一次性渲染。- 拼接模板里必须用反引号,图片路径用
\${arr[i]}插值;若写成单/双引号,\${}不会解析,页面只会出现一段普通文本。 - 用
document.write()输出整个结构,所以 HTML 里不能再手写<div class="box">(笔记里已注释掉),否则会多渲染一份。 - 循环条件用
i < arr.length,不要写<=,否则最后会拼出一个src="undefined"的坏图。
示例二:根据数据渲染柱形图(prompt 收集数据 + 拼接渲染)
js
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
* {
margin: 0;
padding: 0;
}
body {
background-color: #0c143d;
}
.box {
display: flex;
justify-content: space-around;
align-items: flex-end;
width: 800px;
min-height: 300px;
border-left: 1px solid #4b578f;
border-bottom: 1px solid #4b578f;
margin: 0 auto;
padding-top: 50px;
text-align: center;
color: #9799ab;
}
.box>div {
position: relative;
display: flex;
flex-direction: column;
justify-content: space-between;
width: 40px;
height: 0;
background: linear-gradient(#3c99ff, #4489d0, #2283e4);
cursor: pointer;
border-radius: 8px 8px 0 0;
transition: all .2s;
}
.box>div:hover {
animation: bg .5s alternate infinite;
}
@keyframes bg {
to {
box-shadow: 0 5px 29px rgb(53 111 226 / 88%);
background: linear-gradient(#3c99ff, #68aff6, #2283e4);
}
}
.box>div::after {
content: '';
position: absolute;
bottom: 0;
left: 50%;
width: 2px;
height: 10px;
background-color: #4b578f;
transform: translate(-50%, 100%);
}
.box div span {
width: 60px;
margin: -30px 0 -5px -6px;
}
.box div h4 {
width: 70px;
margin: 0 0 -35px -10px;
}
.title {
margin-top: 50px;
text-align: center;
color: #9799ab;
}
</style>
</head>
<body>
<h3 class="title">2099年季度销售数额(单位万)</h3>
<script>
// 功能1: 用户输入4次,并且把数据存放到数组里面
// 1.1 声明一个空的数组
let arr = []
// 1.2 利用循环的形式让用户输入4次,并且把数据追加给数组
for (let i = 1; i <= 4; i++) {
let num = +prompt(`请您输入第${i}季度的销售额`)
arr.push(num)
}
console.log(arr)
// 功能2:根据数组生成柱形图
// 2.1 声明一个空的字符串 str
let str = ''
// 2.2 利用循环拼接字符串,生成多个柱子
for (let i = 0; i < arr.length; i++) {
str += `
<div style="height: ${arr[i]}px;" title="第${i + 1}季度-${arr[i]}万">
<span>${arr[i]}万</span>
<h4>第${i + 1}季度</h4>
</div>
`
}
console.log(str)
// 2.3 把生成的柱子放到box盒子里面进行渲染
document.write(`
<div class="box">
${str}
</div>
`)
</script>
</body>
</html>关键行与易错点
let num = +prompt(...)前的+是把字符串转成数字型;少了它,arr里存的是字符串,后面height: \${arr[i]}px虽然还能用,但后续任何加减运算都会变成字符串拼接。- 收集数据用
arr.push(num),不要用arr = num,否则数组被覆盖成单个值,柱子只剩一根。 - 柱子高度是行内样式
style="height: \${arr[i]}px;",CSS 里.box>div的height: 0会被行内样式覆盖,这是柱形图能“长出来”的原因。 - 索引与季度号的对应:循环变量
i从 0 开始,所以文案里写第\${i + 1}季度,这是最常见的差一错误。
示例三:简易 ATM 存取款机(while 无限循环 + if 多分支)
js
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script>
// 提前声明金额变量,注意要写在 while 循环外面
let money = 100
// 无限循环:页面一打开就不断弹窗
while (true) {
let number = +prompt(`请选择你的操作:
1 取款
2 存款
3 查看余额
4 退出`)
if (number === 1) {
// 取款
let qu = +prompt('请你输入取款金额')
money -= qu // 等价于 money = money - qu
} else if (number === 2) {
// 存款
let cun = +prompt('请你输入存款金额')
money += cun // 等价于 money = money + cun
} else if (number === 3) {
// 查看余额
alert(`你的银行卡余额是${money}元`)
} else if (number === 4) {
// 退出条件:只有输入 4 才 break
break
}
}
// 循环结束之后输出提示
document.write(`你的银行卡余额为${money}元,请节约消费`)
</script>
</body>
</html>关键行与易错点
let money = 100必须写在while外面;写进循环里,每轮都被重置成 100,存取款就白做了。+prompt(...)的加号是重点:prompt取回的是字符串,若直接和数字用===比较,'4' === 4永远为 false,break永不执行,页面就变成死循环弹窗。money -= qu/money += cun是复合运算符的简写,等价于money = money - qu和money = money + cun;用+=做加法时两侧必须都是数字,否则会变成字符串拼接(如100变成100100)。- 最后一个分支用
else if (number === 4)而不是else:否则用户输入 5、6、任意字符都会退出,逻辑不严谨。 - 无限循环一定要有
break退出条件,这是while (true)能安全使用的前提。
常见错误
- ATM 中输入
4无法退出:现象是弹窗一直循环;原因是prompt返回字符串,与数字比较不相等;修法是先+prompt(...)或Number(...),再比较。 - 存款后余额变成拼接结果:现象是
100 + 100得到100100;原因是取款/存款金额未转数字;修法是输入金额后立即转数字,再进行+=或-=。 - 余额每次都被重置:现象是存取后余额不累积;原因是
money声明在while内部;修法是把money声明在循环外。 - 无限循环停不下来:现象是页面一直弹窗;原因是缺少可达的
break或退出分支写错;修法是在明确条件分支内写break,并先用console.log验证输入值。 - 手风琴/柱形图页面空白:现象是只看到空容器或原始结构;原因是拼接了
str但未放入容器;修法是确认document.write(...)或innerHTML使用了最终str。 - 数字排序结果不对:现象是
100排在34前面;原因是sort()未传比较函数,按字符串比较;修法是升序a - b、降序b - a。
练习
- 改造 ATM:当用户输入不是
1~4时提示“请输入正确操作”,且余额不足时禁止取款。 - 用数组保存 7 张图片路径,循环拼接成手风琴结构并渲染到
.box中。 - 输入 4 个季度销售额,非数字时提示重输,并按最大值等比缩放柱形图高度。
- 对
[88, 78, 100, 34, 99]分别完成升序、降序,并输出最大值和最小值。 - 用选择排序处理
[4, 2, 5, 1, 3],每轮结束后打印当前数组,观察交换过程。
原视频对照
| # | 视频 | 时长 |
|---|---|---|
| 1 | 综合案例-ATM存取款机上 | 06:20 |
| 2 | 综合案例-ATM存取款机下 | 11:25 |
小结
- 交互输入先统一数据类型,再比较和运算。
- 累计状态变量应放在循环外,循环内只更新状态。
- 无限循环必须有明确、可达的退出条件。
- 批量渲染先拼字符串,最后必须挂载到容器。
- 数字排序不要依赖默认
sort(),要显式写比较函数。 - 选择排序重点检查
minIndex初始值、内层起点和交换条件。 - 调试时优先打印输入类型、累计变量、数组和拼接结果。