DAY_20JavaScript 条件语句与循环结构深度学习(二)

10.4 第三种:右下三角(完整可运行 HTML)

html 复制代码
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>九九乘法表 - 第三种(右下三角)</title>
    <style>
        body { font-family: 'Microsoft YaHei', sans-serif; padding: 20px; background: linear-gradient(135deg, #4facfe 0%, #00f2fe 100%); min-height: 100vh; }
        h2 { color: white; text-align: center; }
        table { border-collapse: collapse; table-layout: fixed; width: 900px; margin: 0 auto; }
        td { padding: 8px 12px; text-align: center; font-size: 0.85em; white-space: nowrap; border-radius: 4px; }
        td:not(:empty) { border: 1px solid rgba(255,255,255,0.4); background: rgba(255,255,255,0.15); color: white; }
        td:not(:empty):hover { background: rgba(255,255,255,0.35); transition: 0.2s; }
    </style>
</head>
<body>
    <h2>九九乘法表 · 第三种(右下三角)</h2>
    <script>
        document.write('<table><tbody>');
        
        // 【外层循环】控制行数
        for (var i = 1; i <= 9; i++) {
            document.write('<tr>');
            
            // 【第一个内层循环】输出空单元格(占位)
            // 第1行:9-1=8个空格,第2行:9-2=7个空格...
            // 作用:把有内容的单元格"推"到右边
            for (var j = 1; j <= 9 - i; j++) {
                document.write('<td></td>');     // 空单元格(无内容)
            }
            
            // 【第二个内层循环】输出有内容的单元格
            // 和第一种相同,第i行输出i列
            for (var j = 1; j <= i; j++) {
                document.write('<td>' + j + '&times;' + i + '=' + (j * i) + '</td>');
            }
            
            document.write('</tr>');
        }
        
        document.write('</tbody></table>');
    </script>
</body>
</html>
📝 右对齐的核心技巧

空格数量计算规律:

js 复制代码
总列数 = 9(固定)
第 i 行有内容的列数 = i
第 i 行空格数 = 9 - i

示例:
第1行:9-1=8个空格 + 1个内容  → 右对齐
第2行:9-2=7个空格 + 2个内容
第3行:9-3=6个空格 + 3个内容
...
第9行:9-9=0个空格 + 9个内容  → 填满整行

执行流程可视化:

复制代码
第1行(i=1):
  循环1: 输出8个空格(j: 1→8)
  循环2: 输出1个内容(j: 1→1)→ 1×1=1

第2行(i=2):
  循环1: 输出7个空格(j: 1→7)
  循环2: 输出2个内容(j: 1→2)→ 1×2=2, 2×2=4

第3行(i=3):
  循环1: 输出6个空格(j: 1→6)
  循环2: 输出3个内容(j: 1→3)→ 1×3=3, 2×3=6, 3×3=9

CSS 技巧:

css 复制代码
td:not(:empty) { 
    /* 只给非空单元格添加样式 */
    border: 1px solid rgba(255,255,255,0.4);
    background: rgba(255,255,255,0.15);
}
  • 作用: 空单元格不显示边框和背景,实现"透明占位"效果
  • 伪类 :not(:empty) :选择所有不为空的 <td> 元素
🎯 知识点提炼

一行两个循环的模式:

复制代码
模式:前补空格 + 后输出内容
应用:表格右对齐、金字塔图案、层次缩进

空间补偿思想:

复制代码
固定总宽度(9列)
实际内容宽度(i列)
补偿空白宽度(9-i列)
→ 实现右对齐视觉效果

与第一种的对比:

维度 第一种(左下) 第三种(右下)
外层循环 i: 1→9 i: 1→9(相同)
内层循环数量 1 个 2 个
空格处理 前补 9-i
视觉效果 左对齐 右对齐
单元格总数 45 个 45+36=81 个(含空格)

10.5 第四种:右上三角(完整可运行 HTML)

html 复制代码
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>九九乘法表 - 第四种(右上三角)</title>
    <style>
        body { font-family: 'Microsoft YaHei', sans-serif; padding: 20px; background: linear-gradient(135deg, #43e97b 0%, #38f9d7 100%); min-height: 100vh; }
        h2 { color: white; text-align: center; }
        table { border-collapse: collapse; table-layout: fixed; width: 900px; margin: 0 auto; }
        td { padding: 8px 12px; text-align: center; font-size: 0.85em; white-space: nowrap; border-radius: 4px; }
        td:not(:empty) { border: 1px solid rgba(255,255,255,0.4); background: rgba(255,255,255,0.15); color: white; }
        td:not(:empty):hover { background: rgba(255,255,255,0.35); transition: 0.2s; }
    </style>
</head>
<body>
    <h2>九九乘法表 · 第四种(右上三角)</h2>
    <script>
        document.write('<table><tbody>');
        // 外层倒序:i 从 9 到 1
        for (var i = 9; i >= 1; i--) {
            document.write('<tr>');
            // 前补 9-i 个空单元格
            for (var j = 1; j <= 9 - i; j++) {
                document.write('<td></td>');
            }
            // 输出有内容的单元格
            for (var j = 1; j <= i; j++) {
                document.write('<td>' + j + '&times;' + i + '=' + (j * i) + '</td>');
            }
            document.write('</tr>');
        }
        document.write('</tbody></table>');
    </script>
</body>
</html>
📝 代码解释:第四种(右上三角)- 倒序 + 前补空格

第四种 = 第二种(左上)+ 空格偏移

js 复制代码
// 第三种:右下三角(正序 + 前补空格)
for (var i = 1; i <= 9; i++) {       // 正序 i: 1→9
    for (var j = 1; j <= 9 - i; j++) {
        document.write('<td></td>');  // 补空格:9-i 个
    }
    for (var j = 1; j <= i; j++) {
        document.write(/* 内容 */);  // 内容:i 个
    }
}

// 第四种:右上三角(倒序 + 前补空格)
for (var i = 9; i >= 1; i--) {       // 倒序 i: 9→1
    for (var j = 1; j <= 9 - i; j++) {
        document.write('<td></td>');  // 补空格:9-i 个(第1行i=9→0个空格)
    }
    for (var j = 1; j <= i; j++) {
        document.write(/* 内容 */);  // 内容:i 个(第1行i=9→9个内容)
    }
}

第四种空格数量分析(倒序遍历):

复制代码
i=9(第1行):空格 = 9-9=0,内容=9个 → 右对齐(但第1行本身满格,不偏移)
i=8(第2行):空格 = 9-8=1,内容=8个
i=7(第3行):空格 = 9-7=2,内容=7个
i=6(第4行):空格 = 9-6=3,内容=6个
...
i=1(第9行):空格 = 9-1=8,内容=1个 → 最右边1个,前补8个空格

视觉效果:

复制代码
第三种(右下三角):    第四种(右上三角):
            1×1=1       1×9=9 2×9=18 ... 9×9=81
        1×2=2 2×2=4       1×8=8 ... 8×8=64
    ...                     ...
1×9=9 ... 9×9=81                   1×1=1

四种形式总览对比:

形式 外层方向 空格位置 顶部 底部
第一种(左下) 正序 1→9 无空格 少(1个) 多(9个)
第二种(左上) 倒序 9→1 无空格 多(9个) 少(1个)
第三种(右下) 正序 1→9 前补 9-i 个 少+靠右 多+靠左
第四种(右上) 倒序 9→1 前补 9-i 个 多+靠右 少+靠右

四种形式的生成规律:

复制代码
内容部分(所有形式相同):每行第i轮输出 i 个乘法式
                          内层 j: 1→i

变化点:
① 顶多底少 vs 顶少底多:外层 9→1(倒序) vs 1→9(正序)
② 左对齐 vs 右对齐:    有无前置空格(9-i 个)

10.6 九九乘法表知识点提炼

渲染错误: Mermaid 渲染失败: Parse error on line 12: ... td:not(:empty) 有内容 9-i 个空格 = -----------------------^ Expecting 'SPACELINE', 'NL', 'EOF', got 'SPACELIST'


11 跳转语句:break 与 continue

11.1 break 语句

作用: 结束整个循环(或 switch-case)
true
true
false
false
开始
i = 0
i <= 10?
i === 5?
结束整个循环
输出 i
i++

11.2 continue 语句

作用: 跳过本次循环的剩余语句,进入下一次循环
说明: mindmap 语法在部分 Markdown 预览器(旧版 Mermaid、部分 IDE)中不渲染或报错 。下面改用 flowchart + 子图 ,兼容性更好;并附表格作纯文本备用。
九九乘法表 知识点
外层循环:控制行数;正序 1→9 底行最宽,或倒序 9→1 顶行最宽
内层循环:j 从 1 到 i,每行输出 i 个乘法式
右对齐:每行先输出 9 减 i 个空单元格,再输出算式
样式:仅非空单元格加边框(如 CSS 选择器 not-empty)
四种形态:左下① 左上② 右下③ 右上④

知识点速查表(不依赖图表也能读):

模块 要点
外层循环 控制行;1→9 正序则底行最宽,9→1 倒序则顶行最宽
内层循环 j1i,每行输出 i 个乘法式
空格 先输出 9 - i 个空 <td>,再输出算式,实现右对齐三角
样式 常用 td:not(:empty) 只给有内容的单元格加边框,空占位格无框
四种形态 ①左下 ②左上(外层倒序)③右下(加空格)④右上(倒序+空格)

11.3 break 与 continue 完整对比案例(完整可运行 HTML)

html 复制代码
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>break 与 continue 对比</title>
    <style>
        body { font-family: 'Microsoft YaHei', sans-serif; padding: 20px; background: #f5f5f5; }
        .container { display: flex; gap: 20px; flex-wrap: wrap; }
        .card { flex: 1; min-width: 280px; background: white; border-radius: 10px; padding: 20px; box-shadow: 0 2px 8px rgba(0,0,0,0.1); }
        .card h3 { margin-top: 0; }
        .break-card h3 { color: #f44336; }
        .continue-card h3 { color: #FF9800; }
        .nums { display: flex; flex-wrap: wrap; gap: 8px; margin: 15px 0; }
        .num { width: 40px; height: 40px; display: flex; align-items: center; justify-content: center; border-radius: 50%; font-weight: bold; font-size: 1.1em; }
        .printed { background: #4CAF50; color: white; }
        .skipped { background: #FFF3E0; color: #FF9800; border: 2px dashed #FF9800; }
        .stopped { background: #FFEBEE; color: #f44336; border: 2px dashed #f44336; }
        .description { background: #f9f9f9; border-radius: 6px; padding: 12px; font-size: 0.9em; line-height: 1.6; }
        .code { background: #1e1e1e; color: #d4d4d4; padding: 12px; border-radius: 6px; font-family: monospace; font-size: 0.85em; margin-top: 10px; }
        .legend { display: flex; gap: 10px; margin-top: 10px; font-size: 0.85em; }
        .legend-item { display: flex; align-items: center; gap: 5px; }
        .dot { width: 16px; height: 16px; border-radius: 50%; }
    </style>
</head>
<body>
    <div class="container">
        <div class="card continue-card">
            <h3>continue:跳过第 5 次,其他正常输出</h3>
            <div class="description">
                遇到 i===5 时,跳过本次循环后面的语句,<strong>直接进入下一次循环</strong>。循环不会终止。
            </div>
            <div class="nums" id="continueNums"></div>
            <div class="legend">
                <div class="legend-item"><div class="dot" style="background:#4CAF50"></div> 正常输出</div>
                <div class="legend-item"><div class="dot" style="background:#FFF3E0;border:2px dashed #FF9800"></div> 被跳过</div>
            </div>
            <div class="code">
for (var i = 0; i &lt;= 10; i++) {<br>
&nbsp;&nbsp;if (i === 5) continue;<br>
&nbsp;&nbsp;console.log(i); // 输出:0,1,2,3,4,6,7,8,9,10<br>
}
            </div>
        </div>

        <div class="card break-card">
            <h3>break:遇到第 5 个立即终止</h3>
            <div class="description">
                遇到 i===5 时,立即终止整个循环,<strong>后面的所有迭代都不会执行</strong>。
            </div>
            <div class="nums" id="breakNums"></div>
            <div class="legend">
                <div class="legend-item"><div class="dot" style="background:#4CAF50"></div> 正常输出</div>
                <div class="legend-item"><div class="dot" style="background:#FFEBEE;border:2px dashed #f44336"></div> 被终止</div>
            </div>
            <div class="code">
for (var i = 0; i &lt;= 10; i++) {<br>
&nbsp;&nbsp;if (i === 5) break;<br>
&nbsp;&nbsp;console.log(i); // 输出:0,1,2,3,4<br>
}
            </div>
        </div>
    </div>

    <script>
        // 演示 continue
        var continueContainer = document.getElementById('continueNums');
        for (var i = 0; i <= 10; i++) {
            var div = document.createElement('div');
            div.className = 'num';
            div.textContent = i;
            if (i === 5) {
                div.classList.add('skipped');
                div.title = '被 continue 跳过';
            } else {
                div.classList.add('printed');
            }
            continueContainer.appendChild(div);
        }

        // 演示 break
        var breakContainer = document.getElementById('breakNums');
        for (var i = 0; i <= 10; i++) {
            var div = document.createElement('div');
            div.className = 'num';
            div.textContent = i;
            if (i >= 5) {
                div.classList.add('stopped');
                div.title = i === 5 ? '触发 break,循环终止' : '未被执行';
            } else {
                div.classList.add('printed');
            }
            breakContainer.appendChild(div);
        }
    </script>
</body>
</html>
📝 代码解释:break 与 continue 核心区别

两个核心概念:

js 复制代码
// continue:跳过本次,继续下次
for (var i = 0; i <= 10; i++) {
    if (i === 5) continue;  // 跳过 i=5,但循环继续
    console.log(i);         // 输出:0,1,2,3,4,6,7,8,9,10(少了5)
}

// break:立即结束整个循环
for (var i = 0; i <= 10; i++) {
    if (i === 5) break;     // i=5时,整个循环终止
    console.log(i);         // 输出:0,1,2,3,4(到4就停了)
}

continue 执行流程(i===5 时):

复制代码
正常迭代:
  i++ → 判断 i<=10 → 执行循环体 → 执行 console.log(i)

continue 迭代(i=5):
  遇到 continue →【跳过】console.log(5) → 直接 i++ → 判断 i<=10 → 继续

break 执行流程(i===5 时):

复制代码
正常迭代:
  i++ → 判断 i<=10 → 执行循环体 → 执行 console.log(i)

break 迭代(i=5):
  遇到 break →【立即退出循环】→ 后续 6,7,8,9,10 都不执行

DOM 可视化代码解析:

js 复制代码
// continue 演示:始终创建所有圆圈,但 i=5 标记为"跳过"
for (var i = 0; i <= 10; i++) {
    var div = document.createElement('div');
    div.textContent = i;
    if (i === 5) {
        div.classList.add('skipped');    // 橙色虚线圆(被跳过)
        div.title = '被 continue 跳过';  // 鼠标悬停提示
    } else {
        div.classList.add('printed');    // 绿色实心圆(正常输出)
    }
    continueContainer.appendChild(div);
}
// 注意:所有 11 个圆圈都创建了,只是 5 的样式不同

// break 演示:i>=5 都标记为"未执行"
for (var i = 0; i <= 10; i++) {
    var div = document.createElement('div');
    div.textContent = i;
    if (i >= 5) {
        div.classList.add('stopped');    // 红色虚线圆(被终止)
        div.title = i === 5 ? '触发 break,循环终止' : '未被执行';
    } else {
        div.classList.add('printed');    // 绿色实心圆(已执行)
    }
    breakContainer.appendChild(div);
}
// 注意:这里用演示目的创建了所有圆圈,实际代码中 break 后面的迭代不会运行

⚠️ 常见混淆点:

js 复制代码
// ❌ 误区1:continue 会跳到循环结束
// ✅ 正确:continue 只跳过本次的"剩余语句",循环继续
for (var i = 0; i < 5; i++) {
    if (i === 2) continue;
    console.log(i);  // 输出 0, 1, 3, 4(不是 0, 1)
}

// ❌ 误区2:break 只是跳过一次
// ✅ 正确:break 是终止整个循环
for (var i = 0; i < 5; i++) {
    if (i === 2) break;
    console.log(i);  // 输出 0, 1(i=2 时退出循环)
}

实际应用场景:

语句 典型用途 示例场景
continue 过滤特定元素 跳过偶数,只处理奇数
continue 跳过无效数据 跳过空值、undefined
break 查找第一个匹配 找到目标立即停止
break 满足条件退出 密码正确,停止重试
break 配合 while(true) 不确定次数的循环

在嵌套循环中的行为:

js 复制代码
// ⚠️ 重要:break/continue 默认只作用于最近的一层循环
for (var i = 0; i < 3; i++) {
    for (var j = 0; j < 3; j++) {
        if (j === 1) break;  // 只退出内层循环,外层继续
        console.log(i, j);
    }
}
// 输出:0,0  1,0  2,0(每次内层 j=1 时退出内层,外层 i 继续)

11.4 break 的高级用法:配合 while(true) 取随机数

html 复制代码
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>break + while(true) 取随机数</title>
    <style>
        body { font-family: 'Microsoft YaHei', sans-serif; padding: 20px; background: #263238; color: #ECEFF1; }
        button { background: #00BCD4; color: white; border: none; padding: 12px 24px; border-radius: 8px; cursor: pointer; font-size: 1em; }
        button:hover { background: #0097A7; }
        .result { font-size: 1.5em; margin: 15px 0; color: #80CBC4; }
        .code { background: #1e1e1e; padding: 20px; border-radius: 8px; margin-top: 20px; font-family: monospace; line-height: 1.8; }
        .k { color: #569CD6; }
        .c { color: #6A9955; }
        .n { color: #B5CEA8; }
    </style>
</head>
<body>
    <h2>break + while(true):取大于 0.99 的随机数</h2>
    <button onclick="run()">运行一次</button>
    <div class="result" id="result">点击按钮查看结果</div>
    
    <div class="code">
        <span class="c">// 使用 while(true) + break,等价于之前的 while(rand &lt;= 0.99)</span><br>
        <span class="k">while</span> (<span class="k">true</span>) {<br>
        &nbsp;&nbsp;&nbsp;&nbsp;<span class="k">var</span> rand = Math.random();<br>
        &nbsp;&nbsp;&nbsp;&nbsp;<span class="k">if</span> (rand > <span class="n">0.99</span>) {<br>
        &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="k">break</span>;  <span class="c">// 满足条件,跳出死循环</span><br>
        &nbsp;&nbsp;&nbsp;&nbsp;}<br>
        }<br>
        console.log(rand);
    </div>

    <script>
        function run() {
            var count = 0;
            
            // 【while(true)】故意创建"死循环"
            while (true) {                    // 条件永远为 true
                var rand = Math.random();     // 生成随机数
                count++;                      // 计数
                
                // 【内部退出条件】通过 break 主动跳出
                if (rand > 0.99) {            // 满足目标条件
                    break;                    // 跳出整个 while 循环
                }
                // 如果不满足,循环继续(回到 while(true))
            }
            
            document.getElementById('result').textContent = 
                '找到:' + rand.toFixed(8) + '(尝试了 ' + count + ' 次)';
        }
    </script>
</body>
</html>
📝 while(true) + break 模式解析

代码等价性:

js 复制代码
// 传统写法
var rand = Math.random();
while (rand <= 0.99) {
    rand = Math.random();
}

// while(true) + break 写法
while (true) {
    var rand = Math.random();
    if (rand > 0.99) {
        break;  // 手动退出
    }
}

优劣对比:

维度 传统 while while(true) + break
可读性 ✅ 条件直观 ⚠️ 需要看到 break 才明白
灵活性 ⚠️ 复杂条件难写 ✅ 多条件判断更灵活
变量初始化 ❌ 需要循环外初始化 ✅ 变量可在循环内声明
退出位置 固定(顶部判断) ✅ 可在循环任意位置 break
适用场景 简单条件循环 复杂逻辑、多退出点

适用场景:

  1. 多退出条件
js 复制代码
while (true) {
    var input = getUserInput();
    if (input === 'quit') break;        // 退出条件1
    if (input === 'exit') break;        // 退出条件2
    if (isTimeout()) break;             // 退出条件3
    processInput(input);
}
  1. 循环中间退出
js 复制代码
while (true) {
    prepareData();              // 前置操作
    var result = processData(); // 处理数据
    if (result.success) break;  // 中间退出
    cleanup();                  // 后置操作
}
  1. 无限服务循环(服务器)
js 复制代码
while (true) {
    var request = waitForRequest();  // 等待请求
    handleRequest(request);          // 处理请求
    // 服务器永远不退出,除非主动停止
}
⚠️ 危险警告
js 复制代码
// ❌ 真·死循环(没有 break)
while (true) {
    console.log('永远不会停止!');
    // 浏览器会卡死!必须强制关闭标签页
}

// ✅ 安全的 while(true)
while (true) {
    // ... 业务逻辑 ...
    if (某个条件) {
        break;  // 保证有退出路径
    }
}

使用建议:

  • ✅ 必须确保 100% 有 break 可达
  • ✅ 添加注释说明退出条件
  • ✅ 考虑添加安全计数器防止意外死循环
  • ❌ 不要在生产代码中滥用(可读性差)

安全防护模式:

js 复制代码
var maxIterations = 1000;  // 安全上限
var iterations = 0;
while (true) {
    if (iterations++ > maxIterations) {
        console.error('循环超时,强制退出');
        break;  // 安全退出
    }
    // ... 正常逻辑 ...
    if (条件满足) break;
}

11.5 break 与 continue 总结

语句 作用域 效果 类比
break switch / 循环 立即退出当前 switch 或循环 跑步途中直接回家
continue 循环 跳过本次循环剩余语句,进入下一次 跑步途中这一圈走捷径

嵌套循环中的 break/continue: 默认只作用于最近的一层循环,不会跳出外层循环。


12 省略大括号的写法

当循环体或分支体只有一条语句 时,可以省略 {},但强烈不推荐在实际项目中使用

html 复制代码
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>省略大括号演示</title>
    <style>
        body { font-family: 'Microsoft YaHei', sans-serif; padding: 20px; background: #f5f5f5; }
        .compare { display: flex; gap: 20px; flex-wrap: wrap; }
        .box { flex: 1; min-width: 300px; background: white; border-radius: 8px; padding: 20px; box-shadow: 0 2px 8px rgba(0,0,0,0.1); }
        pre { background: #1e1e1e; color: #d4d4d4; padding: 15px; border-radius: 6px; overflow-x: auto; }
        .warn { background: #FFF8E1; border: 1px solid #FFC107; border-radius: 6px; padding: 12px; margin-top: 15px; }
        .good { background: #E8F5E9; border: 1px solid #4CAF50; border-radius: 6px; padding: 12px; margin-top: 15px; }
    </style>
</head>
<body>
    <h2>省略大括号:写法对比</h2>
    <div class="compare">
        <div class="box">
            <h3>❌ 省略大括号(不推荐)</h3>
            <pre>for (var i = 0; i &lt; 10; i++)
    console.log('hello', i);</pre>
            <div class="warn">
                ⚠️ 危险:只有紧跟的第一条语句属于循环体。<br>
                如果后来添加第二条语句忘记加括号,会出现逻辑 Bug!
            </div>
        </div>
        <div class="box">
            <h3>✅ 保留大括号(推荐)</h3>
            <pre>for (var i = 0; i &lt; 10; i++) {
    console.log('hello', i);
}</pre>
            <div class="good">
                ✅ 即使只有一条语句,保留括号可以:<br>
                1. 提高可读性<br>
                2. 方便后续添加语句<br>
                3. 避免隐性 Bug
            </div>
        </div>
    </div>

    <script>
        // 省略大括号示例
        for (var i = 0; i < 3; i++)
            console.log('省略括号 hello', i);

        console.log('循环后仍会执行的代码', i); // 循环外的代码

        // 陷阱演示
        if (false)
            console.log('这行不会执行');
        // 下面这行永远执行,不受 if 控制!
        console.log('这行始终执行,不在 if 的管控范围内');
    </script>
</body>
</html>
📝 代码解释:省略大括号的陷阱

语法规则:单条语句可省略括号

js 复制代码
// ✅ 标准写法(推荐)
for (var i = 0; i < 10; i++) {
    console.log('hello', i);  // 大括号明确了循环体范围
}

// ⚠️ 省略大括号(不推荐)
for (var i = 0; i < 10; i++)
    console.log('hello', i);  // 只有这一行属于循环体

陷阱演示:添加第二条语句

js 复制代码
// ❌ 常见错误:以为两行都在循环内
for (var i = 0; i < 3; i++)
    console.log('省略括号 hello', i);  // ← 循环体(会执行3次)
    console.log('循环后仍会执行的代码', i);  // ← 不在循环体内(只执行1次)

// 实际输出:
// 省略括号 hello 0
// 省略括号 hello 1
// 省略括号 hello 2
// 循环后仍会执行的代码 3  ← 循环结束后才执行

if 语句的陷阱:

js 复制代码
// ❌ 危险写法
if (false)
    console.log('这行不会执行');  // ← if 控制的语句
console.log('这行始终执行,不在 if 的管控范围内');  // ← if 外的语句,总是执行

// ✅ 正确写法(添加大括号)
if (false) {
    console.log('这行不会执行');
    console.log('这行也不会执行');  // 现在两行都在 if 内
}

缩进不等于作用域!

js 复制代码
// ❌ 缩进并不能改变作用域
for (var i = 0; i < 3; i++)
    console.log('第一行', i);  // ← 循环体
    console.log('第二行', i);  // ← 不在循环体内(缩进只是视觉效果)

// 相当于:
for (var i = 0; i < 3; i++)
    console.log('第一行', i);
console.log('第二行', i);  // 循环外

为何强烈不推荐:

风险 说明 示例
维护困难 后续添加语句容易忘记加括号 加第二行代码时没注意
逻辑错误 缩进误导,实际作用域不同 以为两行都在循环内
团队协作 代码审查时容易遗漏 别人修改时出错
调试困难 Bug 隐蔽,不易发现 逻辑看起来对,实际错了

最佳实践:

复制代码
✅ 永远使用大括号,即使只有一条语句
✅ 提高代码可读性和可维护性
✅ 避免隐性 Bug
✅ 团队协作更安全

代码规范建议:

js 复制代码
// ✅ 推荐:始终使用大括号
if (condition) {
    doSomething();
}

for (var i = 0; i < n; i++) {
    process(i);
}

while (condition) {
    execute();
}

// ❌ 不推荐:省略大括号
if (condition) doSomething();
for (var i = 0; i < n; i++) process(i);
while (condition) execute();

13 分支作业案例讲解

13.1 案例一:字符串拼接(完整可运行 HTML)

html 复制代码
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>字符串拼接 - 自我介绍生成器</title>
    <style>
        body { font-family: 'Microsoft YaHei', sans-serif; max-width: 600px; margin: 40px auto; padding: 20px; background: #f5f5f5; }
        .form { background: white; border-radius: 12px; padding: 30px; box-shadow: 0 4px 16px rgba(0,0,0,0.1); }
        .form h2 { margin-top: 0; color: #333; text-align: center; }
        .form-group { margin-bottom: 15px; }
        .form-group label { display: block; margin-bottom: 5px; color: #555; font-weight: bold; }
        .form-group input { width: 100%; padding: 10px; border: 2px solid #ddd; border-radius: 8px; box-sizing: border-box; font-size: 1em; }
        .form-group input:focus { outline: none; border-color: #2196F3; }
        button { width: 100%; background: #2196F3; color: white; border: none; padding: 12px; border-radius: 8px; cursor: pointer; font-size: 1.1em; margin-top: 10px; }
        button:hover { background: #1976D2; }
        .result { margin-top: 20px; background: #E3F2FD; border: 2px solid #2196F3; border-radius: 8px; padding: 20px; display: none; }
        .result p { margin: 0; font-size: 1.1em; line-height: 1.8; color: #1565C0; }
    </style>
</head>
<body>
    <div class="form">
        <h2>自我介绍生成器</h2>
        <div class="form-group">
            <label>姓名</label>
            <input type="text" id="name" placeholder="请输入您的姓名">
        </div>
        <div class="form-group">
            <label>性别</label>
            <input type="text" id="gender" placeholder="男 / 女">
        </div>
        <div class="form-group">
            <label>家乡</label>
            <input type="text" id="hometown" placeholder="例如:上海">
        </div>
        <div class="form-group">
            <label>业余爱好</label>
            <input type="text" id="hobby" placeholder="例如:编程、阅读">
        </div>
        <div class="form-group">
            <label>期望薪资(K)</label>
            <input type="number" id="salary" placeholder="例如:15">
        </div>
        <button onclick="generate()">生成自我介绍</button>
        <div class="result" id="result">
            <p id="intro"></p>
        </div>
    </div>

    <script>
        function generate() {
            var name = document.getElementById('name').value || '匿名用户';
            var gender = document.getElementById('gender').value || '未知';
            var hometown = document.getElementById('hometown').value || '未知';
            var hobby = document.getElementById('hobby').value || '未填写';
            var salary = document.getElementById('salary').value || '0';

            // 字符串拼接(+运算符)
            var message = '我的名字叫' + name + ',性别' + gender + 
                          ',我来自' + hometown + ',我的业余爱好是' + hobby + 
                          ',我学习后的期望薪资是' + salary + ' K。';

            document.getElementById('intro').textContent = message;
            document.getElementById('result').style.display = 'block';
        }
    </script>
</body>
</html>
📝 代码解释:字符串拼接与默认值

核心技术:|| 运算符提供默认值

js 复制代码
var name = document.getElementById('name').value || '匿名用户';
//           ↑ 获取输入框的值                    ↑ 如果为空字符串,使用默认值

|| 运算符的短路特性:

js 复制代码
// 逻辑:如果左边为假值(falsy),返回右边的值
值 || 默认值

// 假值(falsy)包括:
// '', 0, false, null, undefined, NaN

示例:
'' || '默认值'      → '默认值'(空字符串是假值)
'实际值' || '默认值' → '实际值'(非空字符串是真值)
0 || 10             → 10(0 是假值)

获取输入并设置默认值:

js 复制代码
// 获取各个输入框的值,如果为空则使用默认值
var name = document.getElementById('name').value || '匿名用户';     // 空→'匿名用户'
var gender = document.getElementById('gender').value || '未知';     // 空→'未知'
var hometown = document.getElementById('hometown').value || '未知';  // 空→'未知'
var hobby = document.getElementById('hobby').value || '未填写';     // 空→'未填写'
var salary = document.getElementById('salary').value || '0';        // 空→'0'

字符串拼接技巧:

js 复制代码
// 方式1:简单拼接(使用 + 运算符)
var message = '我的名字叫' + name + ',性别' + gender + ',我来自' + hometown;

// 方式2:多行拼接(提高可读性)
var message = '我的名字叫' + name + ',性别' + gender + 
              ',我来自' + hometown + ',我的业余爱好是' + hobby + 
              ',我学习后的期望薪资是' + salary + ' K。';

// 方式3:ES6 模板字符串(现代推荐)
var message = `我的名字叫${name},性别${gender},我来自${hometown},
               我的业余爱好是${hobby},我学习后的期望薪资是${salary} K。`;

DOM 操作:

js 复制代码
// 设置文本内容
document.getElementById('intro').textContent = message;
// textContent:纯文本,安全(防止 XSS 攻击)
// innerHTML:HTML 内容,有安全风险

// 显示结果区域
document.getElementById('result').style.display = 'block';
// 从 display: none → display: block

完整执行流程:

复制代码
用户点击按钮
  ↓
触发 generate() 函数
  ↓
① 获取所有输入框的值(空值用默认值替代)
  ↓
② 使用 + 运算符拼接成完整字符串
  ↓
③ 将字符串设置到 #intro 元素的 textContent
  ↓
④ 显示结果区域(display: block)
  ↓
用户看到生成的自我介绍

知识点总结:

技术点 说明 应用场景
** 运算符**
字符串拼接 + 运算符连接字符串 动态生成文本
.value 获取输入框的值 表单数据获取
.textContent 设置纯文本内容 安全地显示用户输入
.style.display 控制元素显示/隐藏 动态UI交互

实际应用场景:

  • ✅ 表单数据收集与展示
  • ✅ 用户信息卡片生成
  • ✅ 简历自动生成
  • ✅ 评论/留言预览

13.2 案例二:阶梯水价(完整可运行 HTML)

html 复制代码
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>阶梯水价计算器</title>
    <style>
        body { font-family: 'Microsoft YaHei', sans-serif; max-width: 500px; margin: 40px auto; padding: 20px; background: #E3F2FD; }
        .calculator { background: white; border-radius: 16px; padding: 30px; box-shadow: 0 8px 32px rgba(33,150,243,0.2); }
        h2 { color: #1565C0; text-align: center; margin-top: 0; }
        .price-table { background: #F5F5F5; border-radius: 8px; padding: 15px; margin: 20px 0; }
        .price-table table { width: 100%; border-collapse: collapse; }
        .price-table th, .price-table td { padding: 8px 12px; text-align: left; border-bottom: 1px solid #ddd; }
        .price-table th { color: #555; }
        input { width: 100%; padding: 12px; border: 2px solid #90CAF9; border-radius: 8px; box-sizing: border-box; font-size: 1.1em; text-align: center; }
        input:focus { outline: none; border-color: #2196F3; }
        button { width: 100%; background: linear-gradient(135deg, #2196F3, #21CBF3); color: white; border: none; padding: 14px; border-radius: 8px; cursor: pointer; font-size: 1.1em; margin-top: 15px; font-weight: bold; }
        button:hover { opacity: 0.9; }
        .result { margin-top: 20px; text-align: center; display: none; }
        .amount { font-size: 2.5em; color: #1565C0; font-weight: bold; }
        .detail { color: #777; font-size: 0.9em; margin-top: 8px; }
        .error { color: #f44336; text-align: center; margin-top: 15px; display: none; }
    </style>
</head>
<body>
    <div class="calculator">
        <h2>💧 阶梯水价计算器</h2>
        <div class="price-table">
            <table>
                <tr><th>用水量</th><th>单价</th></tr>
                <tr><td>0 ~ 220 m³</td><td>4.05 元/m³</td></tr>
                <tr><td>220 ~ 300 m³</td><td>5.80 元/m³</td></tr>
                <tr><td>300 m³ 以上</td><td>8.79 元/m³</td></tr>
            </table>
        </div>
        <input type="number" id="waterInput" placeholder="请输入用水量(m³)" min="0">
        <button onclick="calculate()">计算水费</button>
        <div class="error" id="error">请输入有效的用水量(正数)</div>
        <div class="result" id="result">
            <div class="amount">¥<span id="totalAmount"></span></div>
            <div class="detail" id="detail"></div>
        </div>
    </div>

    <script>
        function calculate() {
            var val = parseFloat(document.getElementById('waterInput').value);
            document.getElementById('error').style.display = 'none';
            document.getElementById('result').style.display = 'none';

            if (isNaN(val) || val < 0) {
                document.getElementById('error').style.display = 'block';
                return;
            }

            var total, detail;
            if (val <= 220) {
                total = 4.05 * val;
                detail = val + ' m³ × 4.05 = ' + total.toFixed(2) + ' 元';
            } else if (val <= 300) {
                var part1 = 220 * 4.05;
                var part2 = (val - 220) * 5.8;
                total = part1 + part2;
                detail = '220m³×4.05 + ' + (val-220).toFixed(0) + 'm³×5.80 = ' + total.toFixed(2) + ' 元';
            } else {
                var part1 = 220 * 4.05;
                var part2 = 80 * 5.8;
                var part3 = (val - 300) * 8.79;
                total = part1 + part2 + part3;
                detail = '220m³×4.05 + 80m³×5.80 + ' + (val-300).toFixed(0) + 'm³×8.79 = ' + total.toFixed(2) + ' 元';
            }

            document.getElementById('totalAmount').textContent = total.toFixed(2);
            document.getElementById('detail').textContent = detail;
            document.getElementById('result').style.display = 'block';
        }
    </script>
</body>
</html>
📝 代码解释:阶梯计价算法

核心知识:if-else if-else 多分支判断

js 复制代码
// 阶梯定价规则:
// 0~220m³:4.05 元/m³
// 220~300m³:5.80 元/m³(超出220的部分)
// 300m³以上:8.79 元/m³(超出300的部分)

① 输入验证:

js 复制代码
var val = parseFloat(document.getElementById('waterInput').value);
//        ↑ parseFloat:将字符串转换为浮点数

// 清空之前的提示
document.getElementById('error').style.display = 'none';
document.getElementById('result').style.display = 'none';

// 验证输入是否合法
if (isNaN(val) || val < 0) {
//  ↑ isNaN:检查是否是非法数字
//             ↑ 检查是否为负数
    document.getElementById('error').style.display = 'block';
    return;  // 提前退出函数
}

② 第一档(0~220m³):简单计算

js 复制代码
if (val <= 220) {
    total = 4.05 * val;  // 直接乘以单价
    detail = val + ' m³ × 4.05 = ' + total.toFixed(2) + ' 元';
    // toFixed(2):保留2位小数
}
  • 示例: 用水 100m³
    • total = 4.05 × 100 = 405 元
    • detail = "100 m³ × 4.05 = 405.00 元"

③ 第二档(220~300m³):分段计算

js 复制代码
else if (val <= 300) {
    var part1 = 220 * 4.05;           // 前220m³按第一档价格
    var part2 = (val - 220) * 5.8;    // 超出220的部分按第二档价格
    total = part1 + part2;            // 总价 = 第一段 + 第二段
    detail = '220m³×4.05 + ' + (val-220).toFixed(0) + 'm³×5.80 = ' + total.toFixed(2) + ' 元';
}
  • 示例: 用水 250m³
    • part1 = 220 × 4.05 = 891 元(前220m³)
    • part2 = (250 - 220) × 5.8 = 30 × 5.8 = 174 元(超出部分)
    • total = 891 + 174 = 1065 元
    • detail = "220m³×4.05 + 30m³×5.80 = 1065.00 元"

④ 第三档(300m³以上):三段计算

js 复制代码
else {
    var part1 = 220 * 4.05;           // 前220m³按第一档
    var part2 = 80 * 5.8;             // 220~300m³(共80m³)按第二档
    var part3 = (val - 300) * 8.79;   // 超出300的部分按第三档
    total = part1 + part2 + part3;    // 总价 = 三段之和
    detail = '220m³×4.05 + 80m³×5.80 + ' + (val-300).toFixed(0) + 'm³×8.79 = ' + total.toFixed(2) + ' 元';
}
  • 示例: 用水 350m³
    • part1 = 220 × 4.05 = 891 元(第一档)
    • part2 = 80 × 5.8 = 464 元(第二档)
    • part3 = (350 - 300) × 8.79 = 50 × 8.79 = 439.5 元(第三档)
    • total = 891 + 464 + 439.5 = 1794.5 元
    • detail = "220m³×4.05 + 80m³×5.80 + 50m³×8.79 = 1794.50 元"

⑤ 显示结果:

js 复制代码
document.getElementById('totalAmount').textContent = total.toFixed(2);  // 显示总金额
document.getElementById('detail').textContent = detail;                 // 显示计算明细
document.getElementById('result').style.display = 'block';              // 显示结果区域

关键函数说明:

函数 作用 示例
parseFloat() 字符串转浮点数 parseFloat('3.14') → 3.14
isNaN() 检查是否为非法数字 isNaN('abc') → true
.toFixed(n) 保留n位小数 (3.1415).toFixed(2) → '3.14'

算法特点:

  • 分段累加:每一档的费用分开计算,最后求和
  • 边界清晰:<=220、<=300、else 三个分支互斥
  • 易于扩展:新增阶梯只需添加 else if 分支

实际应用场景:

  • 💧 水电燃气阶梯计价
  • 📱 手机流量套餐计费
  • 🚕 出租车分段计价
  • 💰 累进税率计算

可视化执行流程:

复制代码
输入用水量
  ↓
parseFloat 转换为数字
  ↓
验证是否合法(isNaN、<0)
  ↓
├─ 合法 → 判断所属区间
│   ├─ val<=220 → 单价计算
│   ├─ 220<val<=300 → 两段计算
│   └─ val>300 → 三段计算
│   ↓
│   显示结果
│
└─ 不合法 → 显示错误提示

13.3 案例三:体重判断(完整可运行 HTML)

html 复制代码
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>体型判断工具</title>
    <style>
        body { font-family: 'Microsoft YaHei', sans-serif; max-width: 480px; margin: 40px auto; padding: 20px; background: #FFF3E0; }
        .card { background: white; border-radius: 16px; padding: 30px; box-shadow: 0 8px 24px rgba(255,152,0,0.2); }
        h2 { color: #E65100; text-align: center; margin-top: 0; }
        .input-group { margin: 20px 0; }
        input[type=range] { width: 100%; height: 6px; appearance: none; background: linear-gradient(to right, #FF9800, #FF5722); border-radius: 3px; outline: none; }
        .weight-display { text-align: center; font-size: 3em; font-weight: bold; color: #E65100; margin: 10px 0; }
        button { width: 100%; background: linear-gradient(135deg, #FF9800, #FF5722); color: white; border: none; padding: 14px; border-radius: 8px; cursor: pointer; font-size: 1.1em; font-weight: bold; }
        .result { text-align: center; margin-top: 20px; display: none; }
        .category { font-size: 2.5em; font-weight: bold; margin: 10px 0; }
        .range-hint { color: #999; font-size: 0.85em; }
        .scale { display: flex; justify-content: space-between; margin-top: 5px; font-size: 0.75em; color: #bbb; }
    </style>
</head>
<body>
    <div class="card">
        <h2>体型判断工具</h2>
        <div class="input-group">
            <div class="weight-display"><span id="weightVal">80</span> kg</div>
            <input type="range" id="weightSlider" min="30" max="250" value="80" 
                   oninput="document.getElementById('weightVal').textContent=this.value">
            <div class="scale"><span>30kg</span><span>140kg</span><span>250kg</span></div>
        </div>
        <button onclick="judge()">判断体型</button>
        <div class="result" id="result">
            <div class="category" id="category"></div>
            <div class="range-hint" id="hint"></div>
        </div>
    </div>

    <script>
        var categories = [
            { max: 60,  label: '偏瘦 🥢', hint: '体重低于 60kg', color: '#2196F3' },
            { max: 80,  label: '骨感 💃', hint: '60 ~ 80kg', color: '#4CAF50' },
            { max: 100, label: '苗条 ✨', hint: '80 ~ 100kg', color: '#8BC34A' },
            { max: 120, label: '健康 💪', hint: '100 ~ 120kg', color: '#FF9800' },
            { max: 140, label: '丰满 🌸', hint: '120 ~ 140kg', color: '#FF5722' },
            { max: 180, label: '微胖 🌟', hint: '140 ~ 180kg', color: '#E91E63' },
            { max: Infinity, label: '偏胖 🏋️', hint: '180kg 以上', color: '#9C27B0' }
        ];

        function judge() {
            var weight = parseInt(document.getElementById('weightSlider').value);
            var result = categories.find(function(c) { return weight < c.max; });
            
            document.getElementById('category').textContent = result.label;
            document.getElementById('category').style.color = result.color;
            document.getElementById('hint').textContent = '体重范围:' + result.hint;
            document.getElementById('result').style.display = 'block';
        }
    </script>
</body>
</html>
📝 代码解释:数组查找与动态样式

核心知识:数组 + find 方法

① 数据结构:配置数组

js 复制代码
var categories = [
    { max: 60,  label: '偏瘦 🥢', hint: '体重低于 60kg', color: '#2196F3' },
    { max: 80,  label: '骨感 💃', hint: '60 ~ 80kg', color: '#4CAF50' },
    { max: 100, label: '苗条 ✨', hint: '80 ~ 100kg', color: '#8BC34A' },
    // ... 更多分类
    { max: Infinity, label: '偏胖 🏋️', hint: '180kg 以上', color: '#9C27B0' }
];
// 数组中每个对象包含:最大值、标签、提示、颜色
// Infinity:JavaScript 表示无穷大的特殊值

② 获取输入值:

js 复制代码
var weight = parseInt(document.getElementById('weightSlider').value);
//            ↑ parseInt:将字符串转换为整数(舍去小数部分)
//                                               ↑ range 输入框的值

③ 查找匹配的分类:

js 复制代码
var result = categories.find(function(c) { 
    return weight < c.max; 
});
// find 方法:遍历数组,返回第一个满足条件的元素

find 方法执行流程:

复制代码
假设 weight = 75

第1次迭代:c = {max: 60, ...}
  判断:75 < 60? → false → 继续

第2次迭代:c = {max: 80, ...}
  判断:75 < 80? → true → 返回这个对象
  result = { max: 80, label: '骨感 💃', hint: '60 ~ 80kg', color: '#4CAF50' }

停止查找

为什么最后一个用 Infinity?

js 复制代码
// 如果所有 max 都不满足,最终会匹配 Infinity
weight < Infinity  // 永远为 true(任何数字都小于无穷大)
// 这样可以保证一定能找到匹配项,避免 find 返回 undefined

④ 显示结果并应用样式:

js 复制代码
// 设置分类文本
document.getElementById('category').textContent = result.label;  // '骨感 💃'

// 设置动态颜色
document.getElementById('category').style.color = result.color;  // '#4CAF50'

// 设置提示文本
document.getElementById('hint').textContent = '体重范围:' + result.hint;  // '体重范围:60 ~ 80kg'

// 显示结果区域
document.getElementById('result').style.display = 'block';

⑤ 实时交互:oninput 事件

html 复制代码
<input type="range" id="weightSlider" min="30" max="250" value="80" 
       oninput="document.getElementById('weightVal').textContent=this.value">
<!--    ↑ 滑动时实时更新显示的数字                                      ↑ 当前滑块的值 -->

关键API说明:

API 作用 示例
parseInt() 字符串转整数 parseInt('75.9') → 75
Array.find() 查找数组中第一个满足条件的元素 arr.find(item => item > 10)
.style.color 动态设置文本颜色 element.style.color = '#FF0000'
oninput 输入框值变化时触发事件 οninput="updateValue()"
Infinity 表示无穷大 100 < Infinity → true

算法优势:

  • 数据驱动:分类规则存在数组中,易于维护
  • 自动匹配:find 方法自动查找,无需写多个 if-else
  • 易于扩展:新增分类只需在数组中添加对象
  • 动态样式:通过 .style 属性动态设置颜色

传统写法 vs 现代写法对比:

js 复制代码
// ❌ 传统写法:多个 if-else
if (weight < 60) {
    label = '偏瘦 🥢';
    color = '#2196F3';
} else if (weight < 80) {
    label = '骨感 💃';
    color = '#4CAF50';
} else if (weight < 100) {
    // ...
}

// ✅ 现代写法:数据驱动 + find
var categories = [/* 配置数组 */];
var result = categories.find(c => weight < c.max);

实际应用场景:

  • 📊 数据分级展示(成绩等级、信用评分)
  • 🎯 动态样式切换(根据数据变化颜色)
  • 📈 阈值判断(温度预警、库存预警)
  • 🏆 等级系统(用户等级、VIP等级)

13.4 案例四:闰年判断(完整可运行 HTML)

html 复制代码
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>闰年判断器</title>
    <style>
        body { font-family: 'Microsoft YaHei', sans-serif; max-width: 500px; margin: 40px auto; padding: 20px; background: #E8EAF6; }
        .card { background: white; border-radius: 16px; padding: 30px; box-shadow: 0 8px 24px rgba(63,81,181,0.2); }
        h2 { color: #3F51B5; text-align: center; margin-top: 0; }
        .rule { background: #F5F5F5; border-radius: 8px; padding: 15px; margin: 15px 0; font-size: 0.9em; line-height: 1.8; }
        .rule h4 { margin: 0 0 8px; color: #555; }
        input { width: 100%; padding: 12px; border: 2px solid #C5CAE9; border-radius: 8px; box-sizing: border-box; font-size: 1.2em; text-align: center; }
        input:focus { outline: none; border-color: #3F51B5; }
        button { width: 100%; background: linear-gradient(135deg, #3F51B5, #673AB7); color: white; border: none; padding: 14px; border-radius: 8px; cursor: pointer; font-size: 1.1em; font-weight: bold; margin-top: 15px; }
        .result { text-align: center; margin-top: 20px; padding: 20px; border-radius: 8px; display: none; }
        .leap { background: #E8F5E9; color: #2E7D32; }
        .non-leap { background: #FFEBEE; color: #C62828; }
        .result .year { font-size: 2em; font-weight: bold; }
        .result .verdict { font-size: 1.5em; margin-top: 5px; }
        .logic { font-size: 0.85em; margin-top: 8px; color: #777; }
    </style>
</head>
<body>
    <div class="card">
        <h2>📅 闰年判断器</h2>
        <div class="rule">
            <h4>闰年规则:</h4>
            ① 非世纪年(不能被100整除):能被 4 整除 → 闰年<br>
            ② 世纪年(能被100整除):必须能被 400 整除 → 闰年<br>
            <strong>综合条件:(year%4===0 && year%100!==0) || year%400===0</strong>
        </div>
        <input type="number" id="yearInput" placeholder="请输入年份" value="2024">
        <button onclick="check()">判断是否是闰年</button>
        <div class="result" id="result">
            <div class="year" id="yearDisplay"></div>
            <div class="verdict" id="verdict"></div>
            <div class="logic" id="logic"></div>
        </div>
    </div>

    <script>
        function check() {
            var year = parseInt(document.getElementById('yearInput').value);
            
            if (isNaN(year)) {
                alert('请输入有效的年份!');
                return;
            }

            var isLeap = (year % 4 === 0 && year % 100 !== 0) || (year % 400 === 0);
            var resultEl = document.getElementById('result');
            
            document.getElementById('yearDisplay').textContent = year + ' 年';
            document.getElementById('verdict').textContent = isLeap ? '✅ 是闰年!' : '❌ 不是闰年';
            
            var logicText = '';
            if (year % 400 === 0) {
                logicText = year + ' 能被 400 整除(世纪年闰年)';
            } else if (year % 100 === 0) {
                logicText = year + ' 能被 100 整除但不能被 400 整除(世纪年平年)';
            } else if (year % 4 === 0) {
                logicText = year + ' 能被 4 整除且不是世纪年(非世纪年闰年)';
            } else {
                logicText = year + ' 不能被 4 整除(平年)';
            }
            document.getElementById('logic').textContent = logicText;
            
            resultEl.className = 'result ' + (isLeap ? 'leap' : 'non-leap');
            resultEl.style.display = 'block';
        }
    </script>
</body>
</html>
📝 代码解释:闰年判断的复合逻辑

核心知识:逻辑运算符的复合使用

① 闰年规则(天文学定义):

复制代码
规则1:能被 4 整除 → 闰年(基本规则)
规则2:能被 100 整除 → 平年(世纪年例外)
规则3:能被 400 整除 → 闰年(世纪年闰年)

综合逻辑:
(能被4整除 且 不能被100整除) 或 (能被400整除)

② JavaScript 表达式:

js 复制代码
var isLeap = (year % 4 === 0 && year % 100 !== 0) || (year % 400 === 0);
//            ↑ 条件1:非世纪年闰年           ↑ 或      ↑ 条件2:世纪年闰年
//            (year % 4 === 0 && year % 100 !== 0):能被4整除但不能被100整除
//                                                  || (year % 400 === 0):或者能被400整除

③ 逻辑拆解(优先级):

js 复制代码
// 优先级:&& 高于 ||
// 相当于:
var isLeap = (条件A && 条件B) || 条件C;

// 展开:
var 条件A = (year % 4 === 0);      // 能被 4 整除
var 条件B = (year % 100 !== 0);    // 不能被 100 整除
var 条件C = (year % 400 === 0);    // 能被 400 整除

var isLeap = (条件A && 条件B) || 条件C;

④ 典型年份测试:

js 复制代码
// 示例1:2024(非世纪年,能被4整除)
2024 % 4 === 0     // true
2024 % 100 !== 0   // true(2024 % 100 = 24,不为0)
(true && true) || false → true → 闰年 ✅

// 示例2:1900(世纪年,能被100整除但不能被400整除)
1900 % 4 === 0     // true
1900 % 100 !== 0   // false(1900 % 100 = 0)
1900 % 400 === 0   // false(1900 % 400 = 300)
(true && false) || false → false → 平年 ❌

// 示例3:2000(世纪年,能被400整除)
2000 % 4 === 0     // true
2000 % 100 !== 0   // false
2000 % 400 === 0   // true
(true && false) || true → true → 闰年 ✅

// 示例4:2023(不能被4整除)
2023 % 4 === 0     // false(2023 % 4 = 3)
2023 % 100 !== 0   // true
2023 % 400 === 0   // false
(false && true) || false → false → 平年 ❌

⑤ 详细判断逻辑(用于展示):

js 复制代码
var logicText = '';
if (year % 400 === 0) {
    // 优先级最高:能被400整除,一定是闰年
    logicText = year + ' 能被 400 整除(世纪年闰年)';
} else if (year % 100 === 0) {
    // 次优先级:能被100整除但不能被400整除,一定是平年
    logicText = year + ' 能被 100 整除但不能被 400 整除(世纪年平年)';
} else if (year % 4 === 0) {
    // 再次:能被4整除且不是世纪年,一定是闰年
    logicText = year + ' 能被 4 整除且不是世纪年(非世纪年闰年)';
} else {
    // 最后:不能被4整除,一定是平年
    logicText = year + ' 不能被 4 整除(平年)';
}

⑥ 三元运算符:简洁的条件赋值

js 复制代码
var verdict = isLeap ? '✅ 是闰年!' : '❌ 不是闰年';
//           ↑ 条件   ↑ true时的值  ↑ false时的值

// 等价于:
var verdict;
if (isLeap) {
    verdict = '✅ 是闰年!';
} else {
    verdict = '❌ 不是闰年';
}

⑦ 动态 CSS 类:

js 复制代码
resultEl.className = 'result ' + (isLeap ? 'leap' : 'non-leap');
// 如果是闰年:className = 'result leap'(绿色背景)
// 如果是平年:className = 'result non-leap'(红色背景)

关键运算符总结:

运算符 作用 示例
% 取模(取余数) 10 % 3 → 1
=== 严格相等 5 === 5 → true
!== 严格不等 5 !== 3 → true
&& 逻辑与(两个都true才true) true && false → false
|| 逻辑或(一个true就true) true || false → true
? : 三元运算符(条件表达式) x>10 ? 'big' : 'small'

逻辑优先级:

复制代码
优先级从高到低:
1. % (取模)
2. === 、!== (比较)
3. && (逻辑与)
4. || (逻辑或)

示例:
year % 4 === 0 && year % 100 !== 0 || year % 400 === 0
  ↓ 先计算 %
(year % 4) === 0 && (year % 100) !== 0 || (year % 400) === 0
  ↓ 再计算 === 、!==
(result1) && (result2) || (result3)
  ↓ 再计算 &&
(result4) || (result3)
  ↓ 最后计算 ||
最终结果

实际应用场景:

  • 📅 日历系统(计算2月天数)
  • 🎂 生日提醒(计算年龄)
  • 📊 历史数据分析(按年份统计)
  • 🔄 定期任务调度(每4年执行一次)

14 强化练习题完整解答

练习一:while 循环写四种形式的九九乘法表

(见第 10 章,已完整演示)

练习二:100-200 之间能被 3 或 7 整除的数(完整可运行 HTML)

html 复制代码
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>能被3或7整除的数</title>
    <style>
        body { font-family: 'Microsoft YaHei', sans-serif; padding: 20px; background: #f5f5f5; }
        .result { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 20px; }
        .num { padding: 8px 14px; border-radius: 20px; font-weight: bold; }
        .by3 { background: #E3F2FD; color: #1565C0; }
        .by7 { background: #F3E5F5; color: #6A1B9A; }
        .by37 { background: linear-gradient(135deg, #E3F2FD, #F3E5F5); color: #333; border: 2px solid #9C27B0; }
        .legend { display: flex; gap: 15px; margin-top: 15px; flex-wrap: wrap; }
        .legend-item { display: flex; align-items: center; gap: 6px; }
        .dot { padding: 3px 10px; border-radius: 12px; font-size: 0.85em; }
        .stats { background: white; border-radius: 8px; padding: 15px; margin-top: 15px; box-shadow: 0 2px 8px rgba(0,0,0,0.1); }
    </style>
</head>
<body>
    <h2>100-200 之间能被 3 或 7 整除的数</h2>
    <div class="legend">
        <div class="legend-item"><span class="dot by3">蓝色</span>能被 3 整除</div>
        <div class="legend-item"><span class="dot by7">紫色</span>能被 7 整除</div>
        <div class="legend-item"><span class="dot by37" style="border:2px solid #9C27B0;">边框</span>同时能被 3 和 7 整除</div>
    </div>
    <div class="result" id="result"></div>
    <div class="stats" id="stats"></div>

    <script>
        var container = document.getElementById('result');
        var count3 = 0, count7 = 0, count37 = 0, total = 0;
        
        var i = 100;
        while (i <= 200) {
            if (i % 3 === 0 || i % 7 === 0) {
                var div = document.createElement('div');
                div.textContent = i;
                if (i % 3 === 0 && i % 7 === 0) {
                    div.className = 'num by37';
                    count37++;
                } else if (i % 3 === 0) {
                    div.className = 'num by3';
                    count3++;
                } else {
                    div.className = 'num by7';
                    count7++;
                }
                container.appendChild(div);
                total++;
            }
            i++;
        }
        
        document.getElementById('stats').innerHTML = 
            '共找到 <strong>' + total + '</strong> 个数字:' +
            '仅被3整除 <strong>' + count3 + '</strong> 个,' +
            '仅被7整除 <strong>' + count7 + '</strong> 个,' +
            '同时被3和7整除 <strong>' + count37 + '</strong> 个';
    </script>
</body>
</html>
📝 代码解释:条件过滤与分类统计

核心知识:嵌套条件判断 + 计数器

① 初始化变量:

js 复制代码
var container = document.getElementById('result');  // DOM 容器
var count3 = 0, count7 = 0, count37 = 0, total = 0;  // 计数器
//   ↑ 仅被3整除  ↑ 仅被7整除  ↑ 同时整除  ↑ 总数

② 主循环:while 遍历 100-200

js 复制代码
var i = 100;
while (i <= 200) {
    // 外层条件:能被 3 或 7 整除
    if (i % 3 === 0 || i % 7 === 0) {
        // 满足条件,进行处理
    }
    i++;  // 循环变量更新
}

③ 嵌套分类(三种情况):

js 复制代码
if (i % 3 === 0 || i % 7 === 0) {  // 外层:至少满足一个条件
    var div = document.createElement('div');  // 创建 DOM 元素
    div.textContent = i;  // 设置文本内容
    
    // 内层:精确分类
    if (i % 3 === 0 && i % 7 === 0) {  // 情况1:同时能被 3 和 7 整除
        div.className = 'num by37';     // 特殊样式(渐变+边框)
        count37++;                      // 计数器 +1
    } else if (i % 3 === 0) {          // 情况2:仅能被 3 整除
        div.className = 'num by3';      // 蓝色样式
        count3++;
    } else {                            // 情况3:仅能被 7 整除
        div.className = 'num by7';      // 紫色样式
        count7++;
    }
    
    container.appendChild(div);  // 添加到页面
    total++;                     // 总计数 +1
}

④ 分类逻辑流程图:

复制代码
检查数字 i
  ↓
i%3===0 或 i%7===0?
  ↓ 是
创建 DOM 元素
  ↓
i%3===0 且 i%7===0?
  ↓ 是                ↓ 否
【同时整除】        i%3===0?
count37++           ↓ 是      ↓ 否
样式:by37        【仅被3整除】【仅被7整除】
                  count3++     count7++
                  样式:by3    样式:by7
  ↓
添加到页面,total++

⑤ 典型数字分类:

js 复制代码
// 示例1:105(既能被3整除,也能被7整除)
105 % 3 === 0  // true (105 ÷ 3 = 35)
105 % 7 === 0  // true (105 ÷ 7 = 15)
// 结果:count37++,样式 by37

// 示例2:102(仅能被3整除)
102 % 3 === 0  // true (102 ÷ 3 = 34)
102 % 7 === 0  // false (102 ÷ 7 = 14...4)
// 结果:count3++,样式 by3

// 示例3:112(仅能被7整除)
112 % 3 === 0  // false (112 ÷ 3 = 37...1)
112 % 7 === 0  // true (112 ÷ 7 = 16)
// 结果:count7++,样式 by7

// 示例4:101(都不能整除)
101 % 3 === 0  // false
101 % 7 === 0  // false
// 结果:不进入 if,跳过

⑥ 动态 DOM 创建:

js 复制代码
var div = document.createElement('div');  // 创建 <div> 元素
div.textContent = i;                      // 设置文本(等价于 <div>105</div>)
div.className = 'num by37';               // 设置 CSS 类
container.appendChild(div);               // 添加到容器中

⑦ 统计结果输出:

js 复制代码
document.getElementById('stats').innerHTML = 
    '共找到 <strong>' + total + '</strong> 个数字:' +
    '仅被3整除 <strong>' + count3 + '</strong> 个,' +
    '仅被7整除 <strong>' + count7 + '</strong> 个,' +
    '同时被3和7整除 <strong>' + count37 + '</strong> 个';
// innerHTML:允许插入 HTML 标签(<strong> 加粗)

⑧ 数学验证(100-200 范围):

复制代码
能被 3 整除的数:102, 105, 108, ..., 198(33个)
能被 7 整除的数:105, 112, 119, ..., 196(15个)
同时能被 3 和 7 整除的数:105, 126, 147, 168, 189(5个)

分类计数:
count3 = 33 - 5 = 28(仅被3整除)
count7 = 15 - 5 = 10(仅被7整除)
count37 = 5(同时整除)
total = 28 + 10 + 5 = 43(总数)

验证:28 + 10 + 5 = 43 ✓

知识点总结:

知识点 作用 应用场景
** 逻辑或**
&& 逻辑与 必须同时满足 精确匹配
% 取模运算 判断整除性 倍数检测
嵌套 if 多级分类 精细化筛选
createElement 动态创建 DOM 动态生成内容
appendChild 添加子节点 DOM 操作
计数器模式 统计数量 数据聚合

实际应用场景:

  • 🔢 数据筛选(满足特定条件的记录)
  • 📊 分类统计(按多个维度分类)
  • 🎨 动态样式(根据数据特征应用不同样式)
  • 📈 可视化展示(数据驱动的UI渲染)

练习三:三位数中各位上有3或7的数(完整可运行 HTML)

html 复制代码
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>各位上有3或7的三位数</title>
    <style>
        body { font-family: 'Microsoft YaHei', sans-serif; padding: 20px; background: #f5f5f5; }
        .result { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 20px; }
        .num { padding: 6px 12px; background: white; border-radius: 6px; font-size: 0.9em; box-shadow: 0 1px 4px rgba(0,0,0,0.1); position: relative; overflow: hidden; }
        .digit-3 { color: #f44336; font-weight: bold; }
        .digit-7 { color: #2196F3; font-weight: bold; }
        .stats { background: white; border-radius: 8px; padding: 15px; margin-top: 15px; box-shadow: 0 2px 8px rgba(0,0,0,0.1); }
        h2 { border-left: 4px solid #673AB7; padding-left: 10px; }
    </style>
</head>
<body>
    <h2>100-999 中各位上有 3 或 7 的数字</h2>
    <p style="color:#555">(<span class="digit-3">红色</span>表示含3,<span class="digit-7">蓝色</span>表示含7)</p>
    <div class="result" id="result"></div>
    <div class="stats" id="stats"></div>

    <script>
        var container = document.getElementById('result');
        var count = 0;
        
        for (var n = 100; n <= 999; n++) {
            var hundreds = Math.floor(n / 100);        // 百位
            var tens = Math.floor(n / 10) % 10;        // 十位
            var ones = n % 10;                          // 个位

            if (hundreds === 3 || hundreds === 7 ||
                tens === 3 || tens === 7 ||
                ones === 3 || ones === 7) {
                
                var div = document.createElement('div');
                div.className = 'num';
                
                // 高亮含3或7的位
                var h = (hundreds===3||hundreds===7) ? '<span class="digit-'+(hundreds===3?'3':'7')+'">'+hundreds+'</span>' : hundreds;
                var t = (tens===3||tens===7) ? '<span class="digit-'+(tens===3?'3':'7')+'">'+tens+'</span>' : tens;
                var o = (ones===3||ones===7) ? '<span class="digit-'+(ones===3?'3':'7')+'">'+ones+'</span>' : ones;
                
                div.innerHTML = h + t + o;
                container.appendChild(div);
                count++;
            }
        }
        
        document.getElementById('stats').textContent = '共找到 ' + count + ' 个符合条件的三位数';
    </script>
</body>
</html>
📝 代码解释:数字拆分与位判断

核心知识:数字的各位分离算法

① 三位数拆分公式:

js 复制代码
var n = 237;  // 示例数字

var hundreds = Math.floor(n / 100);       // 百位:237 ÷ 100 = 2.37 → 向下取整 = 2
var tens = Math.floor(n / 10) % 10;       // 十位:237 ÷ 10 = 23 → 23 % 10 = 3
var ones = n % 10;                        // 个位:237 % 10 = 7

算法推导:

复制代码
任意三位数 n = abc(a是百位,b是十位,c是个位)
数学表示:n = 100a + 10b + c

提取百位:n ÷ 100 = a.bc → 向下取整 → a
提取十位:n ÷ 10 = ab → ab % 10 → b
提取个位:n % 10 → c

② 典型数字拆分示例:

js 复制代码
// 示例1:123
hundreds = Math.floor(123 / 100) = Math.floor(1.23) = 1
tens = Math.floor(123 / 10) % 10 = Math.floor(12.3) % 10 = 12 % 10 = 2
ones = 123 % 10 = 3

// 示例2:307
hundreds = Math.floor(307 / 100) = 3
tens = Math.floor(307 / 10) % 10 = 30 % 10 = 0
ones = 307 % 10 = 7

// 示例3:700
hundreds = Math.floor(700 / 100) = 7
tens = Math.floor(700 / 10) % 10 = 70 % 10 = 0
ones = 700 % 10 = 0

③ 条件判断:任一位包含 3 或 7

js 复制代码
if (hundreds === 3 || hundreds === 7 ||   // 百位是 3 或 7
    tens === 3 || tens === 7 ||           // 十位是 3 或 7
    ones === 3 || ones === 7) {           // 个位是 3 或 7
    // 满足任一条件,进行处理
}

逻辑展开:

复制代码
条件1:百位 === 3
条件2:百位 === 7
条件3:十位 === 3
条件4:十位 === 7
条件5:个位 === 3
条件6:个位 === 7

只要满足其中任何一个条件,整个 if 就为 true

④ 动态高亮显示:

js 复制代码
// 根据每一位是否包含 3 或 7,动态生成 HTML
var h = (hundreds===3||hundreds===7) ? 
    '<span class="digit-'+(hundreds===3?'3':'7')+'">'+hundreds+'</span>' : 
    hundreds;

var t = (tens===3||tens===7) ? 
    '<span class="digit-'+(tens===3?'3':'7')+'">'+tens+'</span>' : 
    tens;

var o = (ones===3||ones===7) ? 
    '<span class="digit-'+(ones===3?'3':'7')+'">'+ones+'</span>' : 
    ones;

div.innerHTML = h + t + o;  // 拼接成完整数字

高亮逻辑详解:

js 复制代码
// 以百位为例
var h;
if (hundreds === 3 || hundreds === 7) {
    // 百位是 3 或 7,需要高亮
    if (hundreds === 3) {
        h = '<span class="digit-3">' + hundreds + '</span>';  // 红色
    } else {
        h = '<span class="digit-7">' + hundreds + '</span>';  // 蓝色
    }
} else {
    // 百位不是 3 或 7,普通显示
    h = hundreds;
}

⑤ 完整案例演示:

js 复制代码
// 数字 237 的处理
hundreds = 2  // 不是 3 或 7 → h = 2(普通)
tens = 3      // 是 3 → t = '<span class="digit-3">3</span>'(红色)
ones = 7      // 是 7 → o = '<span class="digit-7">7</span>'(蓝色)
// 最终 HTML:2<span class="digit-3">3</span><span class="digit-7">7</span>
// 显示效果:2³⁷(3是红色,7是蓝色)

// 数字 377 的处理
hundreds = 3  // 是 3 → h = '<span class="digit-3">3</span>'(红色)
tens = 7      // 是 7 → t = '<span class="digit-7">7</span>'(蓝色)
ones = 7      // 是 7 → o = '<span class="digit-7">7</span>'(蓝色)
// 最终 HTML:<span class="digit-3">3</span><span class="digit-7">7</span><span class="digit-7">7</span>
// 显示效果:³⁷⁷(3红色,两个7蓝色)

⑥ 循环范围与计数:

js 复制代码
var count = 0;
for (var n = 100; n <= 999; n++) {  // 遍历所有三位数(100-999)
    // 拆分 + 判断 + 创建 DOM
    if (/* 符合条件 */) {
        count++;  // 计数器 +1
    }
}
// 最终 count 就是符合条件的三位数总数

关键函数总结:

函数 作用 示例
Math.floor() 向下取整 Math.floor(2.9) → 2
% 取模 取余数 23 % 10 → 3
/ 除法 除法运算 237 / 100 → 2.37
.innerHTML 设置 HTML 内容 div.innerHTML = '...'
三元运算符 条件表达式 x>10 ? 'big' : 'small'

数学特性验证:

复制代码
三位数范围:100 ~ 999(共 900 个)

符合条件的数字特征:
- 百位是 3:300-399(100个)
- 百位是 7:700-799(100个)
- 十位是 3:103,113,123...,每百个有 10 个,共 90 个
- 十位是 7:107,117,127...,每百个有 10 个,共 90 个
- 个位是 3:103,113,123...,每10个有 1 个,共 90 个
- 个位是 7:107,117,127...,每10个有 1 个,共 90 个

注意去重(如 337 同时满足多个条件)

实际应用场景:

  • 🔢 数字验证(身份证、银行卡校验位)
  • 🎮 游戏逻辑(数字猜谜、密码破解)
  • 📊 数据分析(统计特定模式的数字)
  • 🎰 彩票系统(数字组合生成与检测)

练习四:100 的阶乘(完整可运行 HTML)

html 复制代码
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>100 的阶乘</title>
    <style>
        body { font-family: 'Microsoft YaHei', sans-serif; padding: 20px; background: #f5f5f5; max-width: 700px; margin: 0 auto; }
        .card { background: white; border-radius: 12px; padding: 30px; box-shadow: 0 4px 16px rgba(0,0,0,0.1); }
        .result { background: #E8F5E9; border: 2px solid #4CAF50; border-radius: 8px; padding: 20px; margin: 20px 0; word-break: break-all; font-family: monospace; font-size: 0.9em; line-height: 1.8; }
        .warning { background: #FFF8E1; border: 1px solid #FFC107; border-radius: 8px; padding: 15px; margin-top: 15px; font-size: 0.9em; }
        .steps { margin-top: 20px; }
        .step { display: flex; align-items: center; gap: 10px; padding: 6px 0; border-bottom: 1px solid #f0f0f0; font-size: 0.85em; }
        .step-num { background: #9C27B0; color: white; border-radius: 50%; width: 24px; height: 24px; display: flex; align-items: center; justify-content: center; font-size: 0.75em; flex-shrink: 0; }
        code { background: #f5f5f5; padding: 3px 8px; border-radius: 4px; font-family: monospace; }
    </style>
</head>
<body>
    <div class="card">
        <h2>100! 的计算</h2>
        <div class="steps" id="steps"></div>
        <div class="result" id="result"></div>
        <div class="warning">
            ⚠️ JavaScript 的 Number 类型是 64 位浮点数,最大精确整数约为 2⁵³ ≈ 9×10¹⁵。<br>
            100! ≈ 9.33×10¹⁵⁷,远超此范围,因此 JavaScript 会用科学计数法表示(精度有损失)。<br>
            在实际项目中,超大整数运算需要使用 <code>BigInt</code> 类型(ES2020+)。
        </div>
    </div>

    <script>
        // 方式一:普通 Number(会有精度损失)
        var result = 1;
        var steps = document.getElementById('steps');
        
        for (var i = 1; i <= 100; i++) {
            result *= i;
        }
        document.getElementById('result').innerHTML = 
            '<strong>100! = </strong>' + result + '<br><br>' +
            '(注意:由于 Number 精度限制,此结果有精度损失,仅供演示)';

        // 展示前5步
        var r = 1;
        for (var i = 1; i <= 5; i++) {
            r *= i;
            var div = document.createElement('div');
            div.className = 'step';
            div.innerHTML = '<div class="step-num">' + i + '</div> 1×2×...×' + i + ' = ' + r;
            steps.appendChild(div);
        }
        var dots = document.createElement('div');
        dots.className = 'step';
        dots.innerHTML = '<div class="step-num">...</div> ...';
        steps.appendChild(dots);
    </script>
</body>
</html>
📝 代码解释:阶乘计算与精度限制

核心知识:累乘循环 + JavaScript 数字类型限制

① 阶乘定义:

复制代码
n! = 1 × 2 × 3 × ... × n

示例:
5! = 1 × 2 × 3 × 4 × 5 = 120
10! = 3,628,800
100! ≈ 9.33 × 10¹⁵⁷(天文数字!)

② 基本累乘算法:

js 复制代码
var result = 1;  // 累乘器初始化为 1(乘法单位元)
for (var i = 1; i <= 100; i++) {
    result *= i;  // result = result * i
}
// 最终 result = 1 × 2 × 3 × ... × 100

执行流程:

复制代码
第1次迭代:result = 1 × 1 = 1
第2次迭代:result = 1 × 2 = 2
第3次迭代:result = 2 × 3 = 6
第4次迭代:result = 6 × 4 = 24
第5次迭代:result = 24 × 5 = 120
...
第100次迭代:result = (99!) × 100 = 100!

③ JavaScript Number 类型限制:

js 复制代码
// JavaScript 的 Number 类型特点:
// - 64位双精度浮点数(IEEE 754 标准)
// - 最大安全整数:2⁵³ - 1 ≈ 9×10¹⁵

console.log(Number.MAX_SAFE_INTEGER);  // 9007199254740991

// 超出范围的问题:
var big = 9007199254740992;
console.log(big);        // 9007199254740992
console.log(big + 1);    // 9007199254740992(❌ 无法精确表示)
console.log(big + 2);    // 9007199254740994(✅ 但跳过了 +1)

// 100! 的量级:
// 100! ≈ 9.33×10¹⁵⁷ >> 9×10¹⁵(超出约 142 个数量级!)

④ 科学计数法输出:

js 复制代码
// JavaScript 自动转为科学计数法
var result = 1;
for (var i = 1; i <= 100; i++) {
    result *= i;
}
console.log(result);  
// 输出:9.33262154439441e+157
// 表示:9.33262154439441 × 10¹⁵⁷
// 注意:这只是近似值,精度已损失

⑤ 展示前5步(教学目的):

js 复制代码
var r = 1;
for (var i = 1; i <= 5; i++) {
    r *= i;  // 累乘
    // 创建 DOM 元素显示步骤
    var div = document.createElement('div');
    div.className = 'step';
    div.innerHTML = '<div class="step-num">' + i + '</div> 1×2×...×' + i + ' = ' + r;
    steps.appendChild(div);
}
// 输出:
// ① 1×2×...×1 = 1
// ② 1×2×...×2 = 2
// ③ 1×2×...×3 = 6
// ④ 1×2×...×4 = 24
// ⑤ 1×2×...×5 = 120

⑥ BigInt 解决方案(ES2020+):

js 复制代码
// 使用 BigInt 处理大整数(精确,不会损失精度)
let result = 1n;  // 注意:1n 表示 BigInt 类型
for (let i = 1n; i <= 100n; i++) {
    result *= i;
}
console.log(result.toString());  // 完整的 158 位数字!

// BigInt 特点:
// ✅ 任意大小的整数
// ✅ 精确计算,无精度损失
// ❌ 不能与 Number 直接混合运算
// ❌ 不能使用 Math 对象方法

⑦ Number vs BigInt 对比:

js 复制代码
// Number 方式(有精度损失)
var n1 = 1;
for (var i = 1; i <= 100; i++) n1 *= i;
console.log(n1);  // 9.33262154439441e+157

// BigInt 方式(精确)
let n2 = 1n;
for (let i = 1n; i <= 100n; i++) n2 *= i;
console.log(n2.toString());
// 93326215443944152681699238856266700490715968264381621468592963895217599993229915608941463976156518286253697920827223758251185210916864000000000000000000000000(完整 158 位)

知识点总结:

知识点 说明 应用
阶乘算法 累乘循环 组合数学、概率计算
累乘器 初始值为 1 乘法累积
Number 限制 最大安全整数 2⁵³-1 理解精度问题
科学计数法 e 表示法 表示极大/极小数
BigInt 任意精度整数 大数运算

实际应用场景:

  • 🧮 组合数学(排列组合 C(n,r) = n! / (r!(n-r)!))
  • 🎲 概率计算(古典概型)
  • 🔐 密码学(RSA 算法中的大数运算)
  • 📊 统计学(分布函数)

⚠️ 注意事项:

复制代码
1. 小阶乘(≤20!):Number 类型足够
2. 中阶乘(21!~100!):Number 有精度损失,但可表示量级
3. 大阶乘(>100!):必须使用 BigInt 或专门库(如 big.js)
4. Web 应用:考虑浏览器兼容性(BigInt 需 ES2020+)

练习五:求 1! + 2! + ... + 20! 的值(完整可运行 HTML)

html 复制代码
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>阶乘求和</title>
    <style>
        body { font-family: 'Microsoft YaHei', sans-serif; padding: 20px; background: #f5f5f5; max-width: 700px; margin: 0 auto; }
        table { width: 100%; border-collapse: collapse; background: white; border-radius: 8px; overflow: hidden; box-shadow: 0 2px 8px rgba(0,0,0,0.1); }
        th { background: #673AB7; color: white; padding: 12px; }
        td { padding: 10px 15px; border-bottom: 1px solid #f0f0f0; font-family: monospace; }
        tr:nth-child(even) td { background: #F3E5F5; }
        .total { background: #673AB7; color: white; font-weight: bold; }
        .total td { border: none; }
    </style>
</head>
<body>
    <h2>1! + 2! + 3! + ... + 20!</h2>
    <table>
        <tr><th>n</th><th>n!</th><th>累加总和</th></tr>
        <tbody id="tbody"></tbody>
    </table>

    <script>
        var tbody = document.getElementById('tbody');
        var totalSum = 0;    // 累加总和
        var factorial = 1;   // 当前阶乘值

        for (var n = 1; n <= 20; n++) {
            factorial *= n;     // 第 n 个阶乘 = 上一个阶乘 × n
            totalSum += factorial;  // 累加

            var tr = document.createElement('tr');
            tr.innerHTML = '<td>' + n + '</td>' +
                           '<td>' + factorial.toExponential(3) + '</td>' +
                           '<td>' + totalSum.toExponential(4) + '</td>';
            tbody.appendChild(tr);
        }

        // 总计行
        var totalRow = document.createElement('tr');
        totalRow.className = 'total';
        totalRow.innerHTML = '<td colspan="2">1! + 2! + ... + 20! =</td>' +
                             '<td>' + totalSum + '</td>';
        tbody.appendChild(totalRow);
    </script>
</body>
</html>
📝 代码解释:阶乘求和算法优化

核心知识:双变量累积 + 算法优化

① 问题分析:1! + 2! + 3! + ... + 20!

复制代码
直观算法(低效):
1! = 1
2! = 1 × 2 = 2
3! = 1 × 2 × 3 = 6
...
每次都从 1 开始重新计算,重复计算量大

优化算法(高效):
1! = 1
2! = 1! × 2 = 1 × 2 = 2
3! = 2! × 3 = 2 × 3 = 6
4! = 3! × 4 = 6 × 4 = 24
...
利用前一次的结果,避免重复计算

② 优化算法实现:

js 复制代码
var totalSum = 0;    // 总和累加器(加法单位元)
var factorial = 1;   // 当前阶乘值(乘法单位元)

for (var n = 1; n <= 20; n++) {
    factorial *= n;      // ① 计算 n!(复用上一次的结果)
    totalSum += factorial;  // ② 累加到总和
    // ...(展示步骤)
}

③ 执行流程详解:

复制代码
迭代1:factorial = 1 × 1 = 1,    totalSum = 0 + 1 = 1
迭代2:factorial = 1 × 2 = 2,    totalSum = 1 + 2 = 3
迭代3:factorial = 2 × 3 = 6,    totalSum = 3 + 6 = 9
迭代4:factorial = 6 × 4 = 24,   totalSum = 9 + 24 = 33
迭代5:factorial = 24 × 5 = 120, totalSum = 33 + 120 = 153
...
迭代20:factorial = 19! × 20 = 20!, totalSum += 20!

④ 算法对比:

js 复制代码
// ❌ 低效算法(每次重新计算,时间复杂度 O(n²))
var totalSum = 0;
for (var n = 1; n <= 20; n++) {
    var factorial = 1;
    for (var i = 1; i <= n; i++) {  // 内层循环,重复计算
        factorial *= i;
    }
    totalSum += factorial;
}
// 计算量:1 + 2 + 3 + ... + 20 = 210 次乘法

// ✅ 高效算法(累积计算,时间复杂度 O(n))
var totalSum = 0;
var factorial = 1;
for (var n = 1; n <= 20; n++) {
    factorial *= n;      // 只需 1 次乘法
    totalSum += factorial;
}
// 计算量:20 次乘法(节省 190 次!)

⑤ 动态表格渲染:

js 复制代码
var tr = document.createElement('tr');
tr.innerHTML = '<td>' + n + '</td>' +              // n 列
               '<td>' + factorial + '</td>' +       // n! 列
               '<td>' + totalSum + '</td>';         // 累加总和列
tbody.appendChild(tr);

⑥ 表格样式优化:

css 复制代码
/* 斑马纹效果(提高可读性)*/
tr:nth-child(even) td { 
    background: #F3E5F5;  /* 偶数行浅紫色背景 */
}

/* 总计行特殊样式 */
.total { 
    background: #673AB7;  /* 深紫色背景 */
    color: white;         /* 白色文字 */
    font-weight: bold;    /* 加粗 */
}

⑦ 数学验证:

复制代码
1! + 2! + 3! + 4! + 5! 
= 1 + 2 + 6 + 24 + 120 
= 153

// JavaScript 验证
var sum = 0, f = 1;
for (var i = 1; i <= 5; i++) {
    f *= i;
    sum += f;
}
console.log(sum);  // 153 ✓

⑧ 知识点总结:

知识点 说明 优势
累积计算 n! = (n-1)! × n 避免重复计算
双变量 factorial(当前阶乘)+ totalSum(总和) 同时维护两个状态
时间复杂度 O(n) vs O(n²) 性能提升 10 倍
动态渲染 表格逐行生成 实时展示过程
:nth-child CSS 伪类选择器 斑马纹效果

算法优化原则:

复制代码
1. 避免重复计算(缓存中间结果)
2. 利用递推关系(n! = (n-1)! × n)
3. 单次遍历完成(不使用嵌套循环)
4. 空间换时间(用 factorial 变量存储中间值)

实际应用场景:

  • 📊 动态报表生成(逐行计算并展示)
  • 🧮 累积统计(总销售额、总点击量)
  • 📈 滚动窗口计算(移动平均)
  • 🎯 递推算法(斐波那契、杨辉三角)

扩展思考:

js 复制代码
// 如果要计算 1! + 2! + ... + 100!,会怎样?
var totalSum = 0;
var factorial = 1n;  // 使用 BigInt 避免精度损失
for (let n = 1n; n <= 100n; n++) {
    factorial *= n;
    totalSum += factorial;
}
console.log(totalSum.toString());
// 结果是一个超大整数(需要 BigInt)

练习六:水仙花数(完整可运行 HTML)

html 复制代码
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>水仙花数</title>
    <style>
        body { font-family: 'Microsoft YaHei', sans-serif; padding: 20px; background: linear-gradient(135deg, #667eea, #764ba2); min-height: 100vh; display: flex; align-items: center; justify-content: center; }
        .card { background: white; border-radius: 16px; padding: 40px; max-width: 600px; width: 100%; }
        h2 { color: #673AB7; text-align: center; margin-top: 0; }
        .definition { background: #F3E5F5; border-radius: 8px; padding: 15px; margin: 15px 0; font-size: 0.9em; line-height: 1.8; }
        .flowers { display: flex; flex-wrap: wrap; gap: 15px; justify-content: center; margin-top: 20px; }
        .flower { background: linear-gradient(135deg, #667eea, #764ba2); color: white; border-radius: 12px; padding: 20px 25px; text-align: center; box-shadow: 0 4px 15px rgba(102,126,234,0.4); }
        .flower .num { font-size: 2.5em; font-weight: bold; }
        .flower .formula { font-size: 0.85em; margin-top: 8px; opacity: 0.9; }
    </style>
</head>
<body>
    <div class="card">
        <h2>🌸 水仙花数(自恋数)</h2>
        <div class="definition">
            <strong>定义:</strong>水仙花数是指一个三位数,它的每个位上的数字的 3 次幂之和等于它本身。<br>
            <strong>公式:</strong>abc = a³ + b³ + c³<br>
            <strong>范围:</strong>100 ~ 999
        </div>
        <div class="flowers" id="flowers"></div>
    </div>

    <script>
        var container = document.getElementById('flowers');
        
        // 【循环遍历】所有三位数(100 ~ 999)
        for (var n = 100; n <= 999; n++) {
            // 【数字拆分】提取各个位上的数字
            var a = Math.floor(n / 100);       // 百位:n÷100取整
            var b = Math.floor(n / 10) % 10;   // 十位:n÷10取整后对10取余
            var c = n % 10;                    // 个位:n对10取余
            
            // 【条件判断】检查是否满足水仙花数定义
            if (a*a*a + b*b*b + c*c*c === n) {
                // 【DOM渲染】找到水仙花数,动态生成展示卡片
                var div = document.createElement('div');
                div.className = 'flower';
                div.innerHTML = '<div class="num">' + n + '</div>' +
                                '<div class="formula">' + a + '³ + ' + b + '³ + ' + c + '³<br>= ' + (a*a*a) + ' + ' + (b*b*b) + ' + ' + (c*c*c) + '<br>= ' + n + '</div>';
                container.appendChild(div);
            }
        }
    </script>
</body>
</html>
📝 算法详解:数字拆分技巧

核心算法:提取各位数字

js 复制代码
对于三位数 n(例如 153):
百位 a = Math.floor(n / 100)        → Math.floor(153/100) = 1
十位 b = Math.floor(n / 10) % 10    → Math.floor(153/10) % 10 = 15 % 10 = 5
个位 c = n % 10                     → 153 % 10 = 3

数学原理解释:

操作 数学含义 示例(n=153) 结果
n / 100 移除个位和十位 153 / 100 = 1.53 1.53
Math.floor(n / 100) 向下取整得百位 floor(1.53) 1
n / 10 移除个位 153 / 10 = 15.3 15.3
Math.floor(n / 10) 取整 floor(15.3) 15
% 10 取最后一位 15 % 10 5
n % 10 直接取个位 153 % 10 3

通用模式:N 位数拆分

js 复制代码
// 任意位数的数字拆分模板
var n = 12345;  // 五位数

var digit1 = n % 10;                          // 个位:5
var digit2 = Math.floor(n / 10) % 10;         // 十位:4
var digit3 = Math.floor(n / 100) % 10;        // 百位:3
var digit4 = Math.floor(n / 1000) % 10;       // 千位:2
var digit5 = Math.floor(n / 10000) % 10;      // 万位:1

// 规律:第 k 位 = Math.floor(n / 10^(k-1)) % 10
🎯 水仙花数特性分析

数学性质:

  1. 三位数范围:100 ~ 999(共 900 个数)
  2. 立方和范围
    • 最小:1³+0³+0³ = 1
    • 最大:9³+9³+9³ = 729+729+729 = 2187
  3. 存在性 :三位水仙花数共有 4 个(153, 370, 371, 407)

验证过程:

js 复制代码
153: 1³ + 5³ + 3³ = 1 + 125 + 27 = 153 ✓
370: 3³ + 7³ + 0³ = 27 + 343 + 0 = 370 ✓
371: 3³ + 7³ + 1³ = 27 + 343 + 1 = 371 ✓
407: 4³ + 0³ + 7³ = 64 + 0 + 343 = 407 ✓

扩展:其他自恋数(Armstrong Number)

复制代码
一位数:0-9 都是自恋数(0¹=0, 1¹=1...)
两位数:不存在
三位数:153, 370, 371, 407
四位数:1634, 8208, 9474(如 1634 = 1⁴+6⁴+3⁴+4⁴)
五位数:54748, 92727, 93084
...
🔧 算法优化思路

当前算法:

  • 时间复杂度:O(n),n=900(遍历所有三位数)
  • 空间复杂度:O(1)

优化方向(不推荐,过度优化):

js 复制代码
// 剪枝优化:百位为 0 或 1 时,立方和不可能 >= 200
for (var a = 1; a <= 9; a++) {
    for (var b = 0; b <= 9; b++) {
        for (var c = 0; c <= 9; c++) {
            var sum = a*a*a + b*b*b + c*c*c;
            var n = a*100 + b*10 + c;
            if (sum === n && n >= 100) {
                console.log(n);
            }
        }
    }
}
  • 虽然遍历次数相同(1000次),但逻辑更清晰
  • 适合扩展到 N 位自恋数
💡 知识点总结
知识点 应用
数字拆分 Math.floor(n/10^k) % 10
幂运算 a*a*aMath.pow(a,3)
循环遍历 for 循环逐一检查
条件筛选 if 判断符合条件的数
DOM 操作 动态生成 HTML 展示结果

练习七:100-200 之间所有的素数(完整可运行 HTML)

html 复制代码
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>素数查找器</title>
    <style>
        body { font-family: 'Microsoft YaHei', sans-serif; padding: 20px; background: #f5f5f5; }
        .nums { display: flex; flex-wrap: wrap; gap: 10px; margin-top: 20px; }
        .num { width: 50px; height: 50px; display: flex; align-items: center; justify-content: center; border-radius: 50%; background: linear-gradient(135deg, #FF6B6B, #FFE66D); font-weight: bold; color: #333; font-size: 0.9em; box-shadow: 0 2px 8px rgba(0,0,0,0.15); }
        .stats { background: white; border-radius: 8px; padding: 15px; margin-top: 15px; box-shadow: 0 2px 8px rgba(0,0,0,0.1); }
        .algo { background: #E8EAF6; border-radius: 8px; padding: 15px; margin-top: 15px; font-size: 0.9em; line-height: 1.8; }
    </style>
</head>
<body>
    <h2>100-200 之间所有的素数(质数)</h2>
    <div class="algo">
        <strong>素数判断算法:</strong>只能被 1 和自身整除的数<br>
        <strong>优化技巧:</strong>只需判断到 √n 即可(因为若 n=a×b,a 和 b 中必有一个 ≤ √n)<br>
        例如判断 101:只需检查 2 到 √101 ≈ 10,即 2~10 之间是否有因数
    </div>
    <div class="nums" id="nums"></div>
    <div class="stats" id="stats"></div>

    <script>
        var container = document.getElementById('nums');
        var primes = [];
        
        // 【外层循环】遍历范围内所有数字
        for (var n = 100; n <= 200; n++) {
            var isPrime = true;  // 【假设】先假设 n 是素数
            
            // 【内层循环】寻找因数,从 2 判断到 √n
            // 关键优化:只需检查到 √n
            for (var i = 2; i <= Math.sqrt(n); i++) {
                // 【整除判断】如果 n 能被 i 整除
                if (n % i === 0) {
                    isPrime = false;  // 找到因数,不是素数
                    break;            // 【提前退出】无需继续检查
                }
            }
            
            // 【结果处理】如果是素数,添加到结果集并渲染
            if (isPrime) {
                primes.push(n);
                var div = document.createElement('div');
                div.className = 'num';
                div.textContent = n;
                container.appendChild(div);
            }
        }
        
        document.getElementById('stats').textContent = 
            '100~200 之间共有 ' + primes.length + ' 个素数';
    </script>
</body>
</html>
📝 素数判断算法深度解析

算法核心思想:试除法(Trial Division)

复制代码
素数定义:只能被 1 和自身整除的数(大于 1)
判断方法:尝试用 2 ~ n-1 之间的所有数去除 n
  - 如果都不能整除 → 素数
  - 如果存在能整除的 → 合数(非素数)

关键优化:只需检查到 √n

复制代码
数学原理:
  假设 n = a × b,且 a ≤ b
  那么 a ≤ √n ≤ b

证明:
  如果 a > √n,那么 b = n/a < n/√n = √n
  这与 a ≤ b 矛盾
  因此,a 和 b 中至少有一个 ≤ √n

结论:
  只需检查 2 ~ √n 之间是否有因数
  如果这个范围没有因数,那么 √n ~ n 之间也不会有

示例演示:判断 101 是否为素数

js 复制代码
n = 101
√101 ≈ 10.05

检查过程:
  101 % 2 = 1  ✗ 不整除
  101 % 3 = 2  ✗ 不整除
  101 % 4 = 1  ✗ 不整除
  101 % 5 = 1  ✗ 不整除
  101 % 6 = 5  ✗ 不整除
  101 % 7 = 3  ✗ 不整除
  101 % 8 = 5  ✗ 不整除
  101 % 9 = 2  ✗ 不整除
  101 % 10 = 1 ✗ 不整除

结论:101 是素数

优化效果:
  原始方法:需要检查 2~100(99 次)
  优化方法:只需检查 2~10(9 次)
  性能提升:91% 减少运算次数
🚀 算法性能分析

时间复杂度:

复制代码
外层循环:O(n),n = 200-100+1 = 101
内层循环:O(√m),m 是当前检查的数

总体复杂度:O(n × √m)
对于 100~200:约 101 × √150 ≈ 1238 次操作

性能对比:

方法 检查范围 101 的检查次数 100~200 总检查次数
朴素法 2 ~ n-1 99 ~10,000
√n 优化 2 ~ √n 9 ~1,238
性能提升 - 91% 87.6%

进一步优化(扩展知识):

  1. 跳过偶数(除了 2)
js 复制代码
if (n === 2) return true;  // 2 是唯一的偶数素数
if (n % 2 === 0) return false;  // 其他偶数都不是素数

// 只检查奇数
for (var i = 3; i <= Math.sqrt(n); i += 2) {
    if (n % i === 0) return false;
}
  • 减少 50% 的检查次数
  1. 埃拉托斯特尼筛法(Sieve of Eratosthenes)
js 复制代码
// 适合批量查找素数(如 1~1000000)
function sieveOfEratosthenes(max) {
    var isPrime = new Array(max + 1).fill(true);
    isPrime[0] = isPrime[1] = false;
    
    for (var i = 2; i * i <= max; i++) {
        if (isPrime[i]) {
            // 筛掉 i 的所有倍数
            for (var j = i * i; j <= max; j += i) {
                isPrime[j] = false;
            }
        }
    }
    
    var primes = [];
    for (var i = 2; i <= max; i++) {
        if (isPrime[i]) primes.push(i);
    }
    return primes;
}
  • 时间复杂度:O(n log log n)
  • 空间复杂度:O(n)
  • 适合查找大范围素数
🎯 知识点总结

嵌套循环的 break 使用:

js 复制代码
for (外层) {
    var flag = true;
    for (内层) {
        if (条件) {
            flag = false;
            break;  // 跳出内层循环
        }
    }
    if (flag) {
        // 根据标志变量判断结果
    }
}

布尔标志变量模式:

复制代码
1. 初始假设为 true(isPrime = true)
2. 循环中寻找反例
3. 找到反例立即置 false 并 break
4. 循环结束后根据标志变量判断结果

Math.sqrt() 的使用:

js 复制代码
Math.sqrt(100)  → 10
Math.sqrt(101)  → 10.04987562112089

注意:
  - sqrt 返回浮点数
  - 在循环条件中使用会反复计算
  - 优化:var limit = Math.sqrt(n); 提前缓存
相关推荐
山北雨夜漫步1 小时前
LangGraph
java·前端·算法
漓漾li1 小时前
每日面试题-前端
前端·react.js·面试
布局呆星1 小时前
Vue3 路由守卫详解:全局守卫、路由独享守卫、组件内守卫
前端·javascript·vue.js
小李子呢02111 小时前
前端八股Vue---ref操作 DOM 元素或组件,调用子组件方法
前端·javascript·vue.js
Yoram2 小时前
Vue3 响应性:跨上下文的传递、转换与作用域控制
前端·vue.js
掘金安东尼2 小时前
开源小工具:掘金福利页「补签卡」按次数自动兑换(Chrome 扩展)
前端·开源
Mike_jia2 小时前
Sirius Scan:开源漏洞扫描利器,重塑企业安全防护体系
前端
知兀2 小时前
【前端】默认导出和命名导出区别
前端
XS0301062 小时前
Servlet+JQuery实现数据库数据渲染到前端页面
前端·servlet·jquery