主题
跳转语句(Day4 3/3)
本页对应 Day04_JavaScript,共 6 段视频,约 40 分钟。
学习目标
- 能够使用 JavaScript 的
document.write()结合<table>、<tbody>、<tr>、<td>输出页面表格,并验证九行九列及内容显示正确。 - 能够分析九九乘法表中行号、列号与单元格内容的关系,使用嵌套
for循环实现正金字塔、倒金字塔等至少四种形式的九九乘法表。 - 能够使用 CSS 选择器(如
:not(:empty))为有内容的单元格设置边框和内边距,并隐藏无内容单元格的边框。 - 能够编写示例代码说明
continue与break在循环中的区别,并验证continue跳过本次循环、break结束整个循环的执行结果。 - 能够正确解释并演示省略大括号时,
if、for、while等结构只将相邻的一条语句视为其代码块,并能说明缩进不影响 JavaScript 的作用域判断。
知识点
break:结束所在 case 或整个循环
为什么需要:有些场景不是“把循环跑完”,而是条件满足后立刻停。比如 switch 中匹配到某个 case 后,不希望继续往下执行;循环中已经找到结果,也没必要继续迭代。break 就是用来“打断”的。
怎么想:先判断 break 处在什么结构里。在 switch case 中,它结束的是“所在的 case”,防止继续穿透到后面的 case;在循环中,它结束的是“整个循环”,一旦执行到 break,循环后面的迭代都不再发生。
怎么做:笔记里的核心规则是:
js
1. 在 switch case 中使用: 结束所在的 case
2. 在循环中使用: 结束循环,一旦执行到break,结束整个循环转写稿里用 for 循环演示过:当 i 等于 5 时执行 break,console.log(i) 不再执行,并且整个循环结束。运行后看到的是 0 1 2 3 4,5 以及后面的 6、7、8、9、10 都没有输出。调试时先看输出停在哪里,再回到 if 条件,就能确认是 break 把整个循环结束了。
js
for (var i = 0; i <= 10; i++) {
if (i === 5) {
break;
}
console.log(i);
}
// 输出:0 1 2 3 4转写稿还提到一种常见用法:用 while (true) 写死循环,在循环里取随机数,当随机数满足条件时用 break 结束循环。这样不必把复杂条件全塞进 while 的循环条件里。
易错点:switch 里的 break 只结束当前 case,不是结束外层循环;循环里的 break 是结束整个循环,不要和 continue 混用。break 后面再写本次循环里的语句没有意义,因为执行不到。
continue:只跳过本次循环
为什么需要:有时某一次循环的数据不需要处理,但后面的循环还要继续。比如遍历到 5 时想跳过 5,但 6、7、8 还要正常输出,这时不能用 break,而要用 continue。
怎么想:continue 的关键词是“本次”。执行到 continue 后,本次循环中它后面的语句不再执行,但循环不会整体结束,下一次循环继续。转写稿里的例子就是:i 等于 5 时 continue,于是 console.log(5) 被跳过,但 i 变成 6 后仍然继续输出。
怎么做:笔记里的规则是:
js
在循环中使用: 跳出本次循环,一旦执行到continue,本次循环中后面语句不再执行,下一次循环继续对应代码:
js
for (var i = 0; i <= 10; i++) {
if (i === 5) {
continue;
}
console.log(i);
}
// 输出:0 1 2 3 4 6 7 8 9 10转写稿的调试过程是:先运行,发现输出 0 1 2 3 4 6 7 8 9 10,少了 5;再检查 if (i === 5) 里执行了 continue,所以 console.log(5) 没有执行。注意在 for 循环里,continue 后仍会执行 i++,所以下一次循环能继续,不会卡在 5。
易错点:continue 只能用于循环中,不要拿去控制 switch;它只跳过本次,不是结束整个循环。若把 continue 误写成 break,输出会从 5 开始全部消失,这是两者最直观的区别。
对比与调试:看输出停在哪里
为什么需要:break 和 continue 都叫“跳转”,但结果完全不同。对比着看,才能避免“想跳过一次却结束整个循环”。
怎么想:先问自己:我是要“这一次不做了”,还是“后面都不做了”?前者用 continue,后者用 break。
怎么做:用同一段循环分别替换关键字,观察输出。continue 版本输出 0 1 2 3 4 6 7 8 9 10;break 版本输出 0 1 2 3 4。转写稿里正是这样对比调试的:先看少了哪个数,再看循环有没有继续。
易错点:不要只看代码“像不像”,要运行看结果;break 和 continue 后面的语句都可能执行不到,写代码时不要把必要逻辑放在它们后面。
本节作业与课堂案例
本节笔记中的作业如下,先保留原题:
1. 课堂案例
2. 强化练习
1. 使用 while 循环写四种形式的九九乘法表
2. 输出100–200之间所有能被3或者7整除的数
3. 输出三位数中,位上有3或者7的数字 100 ~ 999
4. 100 的阶乘 1*2*3....*100
5. 求1!+2!+3!+...+20!的值课堂转写主要围绕第1题展开:四种九九乘法表,以及 continue、break、省略大括号。下面按“为什么需要 → 怎么想 → 怎么做 → 易错点”整理。转写中演示多用 for,作业要求用 while,思路一致:把初始化、条件、更新拆开写即可。
四种九九乘法表:先搭表格骨架
为什么需要:九九乘法表不是规则表格,第一行1个单元格,第二行2个……第九行9个。要先解决“行固定、列不固定”的结构问题。
怎么想:外层循环控制行,内层循环控制本行单元格个数。第一行1个、第二行2个,所以内层次数正好等于当前行号。表格仍用 table > tbody > tr > td 输出。
怎么做:先写样式,否则只输出标签页面看不见。关键样式包括 table-layout: fixed、border-collapse: collapse、td 的边框和内边距。第一种形式的核心循环:
js
document.write("<table><tbody>");
for (let i = 1; i <= 9; i++) {
document.write("<tr>");
for (let g = 1; g <= i; g++) {
document.write("<td>" + g + "×" + i + "=" + (g * i) + "</td>");
}
document.write("</tr>");
}
document.write("</tbody></table>");易错点:漏写 <td> 或 <tr>,页面结构不完整;document.write 拼成 right 会报错。转写中第32行就是把 write 拼错,控制台直接提示行号,改对后恢复。遇到结果不对,先看控制台报错,不要盲目逐行猜。
第二种:倒金字塔
为什么需要:四种形式中第二种是倒序,第一行9个,最后一行1个。
怎么想:内层“第几行就输出几个”的规律不变,只改外层行号方向。
怎么做:外层从9到1,内层仍从1到当前 i:
js
for (let i = 9; i >= 1; i--) {
document.write("<tr>");
for (let g = 1; g <= i; g++) {
document.write("<td>" + g + "×" + i + "=" + (g * i) + "</td>");
}
document.write("</tr>");
}易错点:条件方向写反;忘记输出 tr 开始或结束标签。转写中第二种一开始漏写 td,只写内容不会形成单元格。
第三种:右对齐,用空白单元格“挤”
为什么需要:要让内容靠右,不能随便改单元格显示模式,比较稳的办法是每行仍放9个单元格,前面放空白格,后面放内容格。
怎么想:当前行有 i 个内容格,就需要 9 - i 个空白格。空白格在前,内容格在后,于是内容被挤到右边。
怎么做:一行里写两个并列循环:先输出 9 - i 个空 td,再输出 i 个有内容 td。样式只给非空单元格加边框:
css
td:not(:empty) {
border: 1px solid #000;
padding: 8px;
}易错点:空 td 不能加可见边框,否则会露出空白格;两个循环是并列关系,变量都叫 g 不冲突,因为第一个循环已经结束。转写中强调:不要想当然,要分析作用域和执行顺序。
第四种:倒序加右对齐
为什么需要:第四种是第三种的方向翻转。
怎么想:右对齐结构不变,只把外层 i 从9到1。
怎么做:空白格仍是 9 - i 个,内容格仍是 i 个,内容公式仍是 g × i = g*i。
易错点:漏掉 </tr> 会导致结构错乱;空白格循环和内容格循环要按“先空后内容”的顺序。
continue 与 break
为什么需要:循环中有时要跳过某次,有时要提前结束整个循环。
怎么想:continue 只跳过本次循环剩余语句,下一次继续;break 直接结束整个循环。二者都可用于 for、while、do while。
怎么做:
js
for (let i = 0; i <= 10; i++) {
if (i === 5) continue;
console.log(i);
}
// 输出 0 1 2 3 4 6 7 8 9 10
for (let i = 0; i <= 10; i++) {
if (i === 5) break;
console.log(i);
}
// 输出 0 1 2 3 4易错点:continue 不是结束整个循环;break 在 switch 中结束当前 case,在循环中结束整个循环。转写中还演示了“死循环 + break 取大于0.99随机数”的写法,说明同一需求可以多种写法,但初学要保证能退出。
省略大括号
为什么需要:JS 允许分支和循环省略大括号,代码更短。
怎么想:省略后只认相邻的后一条语句为循环体或分支体,缩进不决定归属。
怎么做:
js
for (let i = 0; i < 10; i++)
console.log("hello", i);易错点:如果再写第二条语句,它不在循环体内;缩进也不会让它进入循环。if/else 同理。初学建议即使只有一句也写大括号,可读性更稳。
课堂画面






代码示例
示例 1:continue 与 break 对比
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>break 与 continue</title>
</head>
<body>
<script>
// 1. continue:跳出本次循环,下一次循环继续
for (var i = 0; i <= 10; i++) {
if (i === 5) {
continue; // i 为 5 时,后面语句不再执行
}
console.log('continue: ' + i); // 0 1 2 3 4 6 7 8 9 10
}
// 2. break:结束整个循环
for (var i = 0; i <= 10; i++) {
if (i === 5) {
break; // i 为 5 时,整个循环直接结束
}
console.log('break: ' + i); // 0 1 2 3 4
}
// 3. break 的常用套路:死循环 + 条件 break
while (true) {
var num = Math.random();
if (num > 0.99) {
console.log('取到大于 0.99 的随机数:' + num);
break; // 条件满足才跳出死循环
}
}
</script>
</body>
</html>要点解释
- 关键行:
if (i === 5) { continue; }—— 一旦执行到continue,本次循环中它后面的console.log就不再执行,但下一次循环照常进行,所以输出里少了5,6 7 8 9 10全在。 - 关键行:把
continue换成break,输出只有0 1 2 3 4——break不只是跳过后面语句,是把整个循环结束了。 - 易错点:两者都只能用在循环(
for、while、do while)里;break还能用在switch case里,作用是结束所在 case,不写break会一直往下穿透。 - 易错点:
while (true)是死循环,循环条件永远不会自己变假,必须靠break退出,否则页面直接卡死。 - 易错点:判断条件用
===全等,别写成=赋值。
示例 2:第一种形式九九乘法表(正金字塔,while/for 嵌套)
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>第一种形式九九乘法表</title>
<style>
table {
width: 900px;
table-layout: fixed;
border-collapse: collapse;
}
td {
border: 1px solid #000;
height: 60px;
padding: 5px;
text-align: center;
}
</style>
</head>
<body>
<script>
document.write('<table><tbody>');
for (var i = 1; i <= 9; i++) { // 外层:控制 9 行
document.write('<tr>');
for (var g = 1; g <= i; g++) { // 内层:第 i 行就循环 i 次
document.write('<td>' + g + ' × ' + i + ' = ' + (g * i) + '</td>');
}
document.write('</tr>');
}
document.write('</tbody></table>');
</script>
</body>
</html>要点解释
- 关键行:
for (var g = 1; g <= i; g++)—— 第 1 行 1 个单元格、第 2 行 2 个……行号i就是单元格个数,这就是不规则表格的规律。 - 关键行:
' × '用的是字符实体,因为内容要输出到文档流,和直接在 HTML 里写一样,直接敲×容易出乱码。 - 关键行:
(g * i)必须加小括号——不加的话是字符串拼接,'1 * 2 = ' + 1 * 2会先拼成'1 * 2 = 1'再乘,结果完全不对。括号的作用就是声明“这是一个整体,先算”。 - 易错点:
<table><tbody>和结束标签必须自己document.write出来,不能只写单元格,否则浏览器会自动补全结构,表格直接乱掉。 - 易错点:
<td>一定要写,只写内容不写td标签,表格里什么都看不见。 - 易错点:内层循环变量不能也叫
i,会和外层冲突,所以换名g;g <= i是因为从 1 开始数,如果从 0 开始就要写g < i。 - 易错点:样式必须提前写好(
border-collapse合并边框、td的边框和高度),否则标签写对了页面上也是一片空白。
示例 3:第三种形式九九乘法表(靠右金字塔 + :not(:empty) 隐藏空白格)
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>第三种形式九九乘法表</title>
<style>
table {
width: 900px;
table-layout: fixed;
border-collapse: collapse;
}
/* 只给有内容的单元格加边框和内边距,空白格就"消失"了 */
td:not(:empty) {
border: 1px solid #000;
height: 60px;
padding: 5px;
text-align: center;
}
</style>
</head>
<body>
<script>
document.write('<table><tbody>');
for (var i = 1; i <= 9; i++) {
document.write('<tr>');
// 第一部分:空白单元格,个数是 9 - i
for (var g = 1; g <= 9 - i; g++) {
document.write('<td></td>');
}
// 第二部分:有内容的单元格,个数是 i
for (var g = 1; g <= i; g++) {
document.write('<td>' + g + ' × ' + i + ' = ' + (g * i) + '</td>');
}
document.write('</tr>');
}
document.write('</tbody></table>');
</script>
</body>
</html>要点解释
- 关键思路:每一行其实都是 9 个单元格,只是分成“空白”和“有内容”两组,空白组把有内容的格子挤到右边,形成靠右的塔形。
- 关键行:
for (var g = 1; g <= 9 - i; g++)—— 当i = 1时是 8 个空白,i = 9时是 0 个空白,最后一行刚好没有空白。 - 关键行:
td:not(:empty)——:empty表示既没有内容也没有子元素,not()把它排除掉,于是只有带内容的格子有边框,空白格看不见。 - 易错点:两个内层循环是并列执行的,前一个循环已经结束了,所以标记变量都叫
g不冲突;但如果是嵌套循环,就绝对不能重名。 - 易错点:空白格必须写成
<td></td>,中间不能有任何空格或换行,否则:empty就不成立,空白格子会带边框显示出来。 - 易错点:写完发现页面全空,先按 F12 看控制台报错,按提示找到出错行号,比一行行猜快得多(本节就踩过
write拼错的坑)。 - 拓展:第四种形式只需把外层
for (var i = 1; i <= 9; i++)改成for (var i = 9; i >= 1; i--),内层代码一个字都不用动,就是倒金字塔。
常见错误
内层循环误用外层变量名 现象:乘法表每行单元格数全一样,或直接死循环。 原因:内层
for又声明了i,覆盖了外层行号,j <= i的条件永远成立。 修法:内层一律换名(j/k),并在写循环前先列出"外层管什么、内层管什么"。只写内容不写
<td>现象:页面一片空白,但检查元素能看到tbody和tr。 原因:document.write拼出的纯文本/字符实体直接落在<tr>里,浏览器按表格模型丢弃。 修法:任何要显示的内容必须包在<td>...</td>中;拼字符串时先写骨架<td></td>,再往里塞内容。write拼写错误导致后续全丢 现象:表格只剩一个<tr>,或整段输出戛然而止,无任何视觉提示。 原因:documet.right之类笔误抛 ReferenceError,脚本中断,后面的write不再执行。 修法:结果不对先按 F12 看 Console 报错行号,按提示定位;不要靠肉眼逐行扫代码。break与continue用反 现象:想跳过 5,结果 5 之后的 6~10 全没了;或想终止循环却只少了一次。 原因:把"结束整个循环"和"结束本次循环"混为一谈。 修法:判断标准——后续还要不要继续迭代?要 →continue;不要 →break。写完先用 1~10 的小循环验证一次。省略大括号后多写了一行 现象:第二条
console.log只输出一次,缩进看起来却像在循环里。 原因:省略{}时只有紧邻的一条语句属于循环体/分支体,缩进不参与语法判定。 修法:只要循环体/分支体超过一条语句就必须补{};建议即便只有一条也保留大括号。用
:empty隐藏空白单元格失效 现象:第三种乘法表左侧空白格仍有边框,表格宽度被撑满。 原因:<td> </td>或<td>\n</td>中含空白字符,不满足:empty的"完全无内容"条件。 修法:空白td写成<td></td>不留任何字符;或改用类名.blank精确控制样式,不依赖:empty。大数阶乘结果末位错乱 现象:
100!输出成一串科学计数法,1!+...+20!求和后个位与手算不符。 原因:超出Number.MAX_SAFE_INTEGER后双精度浮点丢失低位精度。 修法:需要精确值用BigInt(1n、*=、+),或只做字符串/数组模拟进位。
练习
- 用
while重写第一种九九乘法表(禁止使用for),写完后回答:内层循环条件写成j <= i与j < i分别会得到什么图形? - 用死循环 +
break实现:不断生成Math.random(),直到取到大于 0.99 的数为止,输出尝试次数。再用while条件写法实现一遍,比较两种写法各自的适用场景。 - 输出 100~200 之间所有能被 3 或 7 整除的数。要求分别用
continue过滤版和if直接判断版各写一次,并说明两版可读性差异。 - 把第三种(右对齐)乘法表改造为:空白格不加任何 CSS 类,有内容格加
class="cell",样式全部写在.cell上。改完后对比:empty方案,说明哪种更不容易被后续改动破坏。 - 下面代码输出什么?先手写答案再运行验证,然后改成你认可的写法:js
for (let i = 0; i < 3; i++) console.log('A' + i); console.log('B' + i); - 求
1! + 2! + ... + 20!,先用普通Number算,再用BigInt算,对比两者末几位数字,说明差异来源。
原视频对照
| # | 视频 | 时长 |
|---|---|---|
| 1 | 第一种形式九九乘法表 | 09:48 |
| 2 | 第二种形式九九乘法表 | 04:55 |
| 3 | 第三种形式九九乘法表 | 08:21 |
| 4 | 第四种形式九九乘法表 | 05:47 |
| 5 | continue和break | 07:08 |
| 6 | 省略大括号 | 04:38 |
小结
- 图形类输出(乘法表、金字塔)的通用切入点是:先数清"行数由谁控制、每行列数由谁控制",把两者映射到循环变量上,图形自然浮现。
- 四种乘法表之间真正变化的只有两处——外层循环方向和空白格数量(
9 - i),内层内容逻辑几乎零改动。能识别"哪里不变"比能写出代码更有价值。 - 排版类需求优先考虑"结构占位 + 样式隐藏",而不是在 JS 里做视觉判断;把"生成"和"呈现"分开,代码会短很多。
break的典型场景是"次数不确定、达成即止",continue的典型场景是"遍历全部、过滤部分",选错会让循环语义与意图背离。- 结果异常时的排查顺序固定为:控制台报错 → 检查元素看 DOM 结构 → 打印中间变量,不要一上来就通读代码。
- 省略大括号属于风格选项而非语法能力,个人偏好应让位于团队规范;缩进在 JS 里只是给人看的,不构成作用域。
- 涉及阶乘、累加等数值膨胀的场景,先估算量级再选数据类型,浮点精度问题一旦发生无法靠"多算几次"弥补。