🐸 青蛙编程网
首页 / 前端 / JavaScript / 6. 综合练习

综合练习:网页计算器

这是什么:综合实战 = 把变量、函数、DOM、事件全部拼起来,做一个真正能用的网页计算器。

为什么用:恭喜走到毕业章!这一章没有新知识——不把学过的全部拼起来,你只会写片段,不会写完整工具。

如何用:照着「读取 → 计算 → 显示」三步理清流程,再把完整代码贴进在线运行框点「▶ 运行」。

目标与思路

目标界面:两个数字输入框 + 加减乘除四个按钮 + 一行结果。

写之前先想清楚流程,任何交互页面都是这三步:

  1. 读取:拿到两个输入框里的数字
  2. 计算:按运算符算出结果
  3. 显示:把结果写回页面

完整代码

🧪 在线运行
👀 运行结果

💡 代码可直接复制;想改、想跑,点右上「🧪 在线运行场」。

「你会看到」:点 + 显示 9,点 × 显示 18;把第二个框改成 0 再点 ÷,会提示"不能除以 0"。

逐段解读

HTML 部分:

代码 作用
<input type='number' value='6'> 数字输入框,默认值 6
data-op='+' 自定义属性:给按钮"随身携带"一个运算符
onclick='calc(this.dataset.op)' 点击时把按钮携带的运算符传给 calc;this 指"被点的这个按钮"

四个按钮共用一个 calc 函数,只是传的运算符不同——这正是第 3 章说的函数复用。

JS 部分(对应开头说的三步):

代码 作用
Number(...value) 读取输入并转成数字(不转的话 '6' + '3' 会拼成 '63'!)
if / else if 一串 按运算符选择算法
b === 0 判断 除数为 0 时给提示,避免显示 Infinity
textContent = r 显示:把结果写回页面

记忆口诀:读输入、做计算、写结果——所有交互页面,都是这三步的排列组合。

❓ 常见问题

Q1:输入 6 和 3 点 +,结果却是 63?

原因:忘了转数字。输入框的 value 永远是字符串,'6' + '3' 里的 + 被当成"拼接",把两个字符粘在一起。

63

修复三步:① 找到读取输入的两行;② 在外面套上 Number():let a = Number(document.querySelector('#a').value);③ b 同样处理,再点按钮验证。 举一反三:凡是从输入框、URL 参数拿来的数,先用 Number() 过一道再算——"先转型再计算"是铁律。

Q2:把第二个框改成 0 点 ÷,结果显示 Infinity?

原因:数学里除以 0 无解,JS 硬算会得到 Infinity(无穷大)——代码没报错,但这个结果对用户毫无意义。

Infinity

修复三步:① 在做除法前加一个分支:else if (b === 0);② 这个分支里给 r 赋友好提示'不能除以 0';③ 确认它排在真正的除法分支前面,否则轮不到它。 举一反三:好的程序不只算得出,还要"提醒得出"——把用户会手滑的每种输入都提前想好对策。

Q3:点按钮报 Uncaught ReferenceError: calcc is not defined at HTMLButtonElement.onclick?

原因:onclick 里写的函数名和 <script> 里定义的对不上——多半是多打或少打了一个字母,浏览器找不到叫 calcc 的函数。

Uncaught ReferenceError: calcc is not defined
    at HTMLButtonElement.onclick

修复三步:① 看报错里的名字 calcc;② 回 HTML 里找 onclick,对照 <script> 里的 function 名逐字核对;③ 改成完全一致,刷新再点。 举一反三:报错里的 at HTMLButtonElement.onclick 告诉你案发地点在"某个按钮的 onclick 属性"——报错信息会指路,学会读它。

Q4:为什么 '10' - '3' 得 7,'10' + '3' 却是 '103'?

原因:+ 在 JS 里有双重人格:两边都是字符串就拼接,有数字才相加;而 - 只会算减法,遇到字符串会强制转成数字。所以带引号的 '10' - '3' 反而算出了 7。

7
103

修复三步:① 记住结论:+ 可能拼接,- * / 强转数字;② 别依赖强转——该转的手动 Number(),代码意图一目了然;③ 拿不准类型就 typeof 问一句。 举一反三:+ 的双重人格是 JS 最著名的坑之一,规则记不住就统一先 Number() 再算,永远安全。

Q5:输入框留空点按钮,结果算出了 0?

原因:空字符串被 Number('') 转成了 0——JS 规定空串的数字形式就是 0,于是"什么都没填"被当成了"填了 0"参与计算。

Number('')   // 0

修复三步:① 计算前先判断:if (value === '') 就给提示"请先输入";② 通过检查再 Number() 和计算;③ 两条路径各测一遍——留空、填数。 举一反三:Number 对怪输入很宽容:空串是 0、'abc' 是 NaN——宽容不等于正确,边界输入要自己把关。

⚠️ 新手翻车现场

翻车一:字符串冒充数字,加法变拼接

function calc(op) {
  let a = document.querySelector('#a').value
  let b = document.querySelector('#b').value
  document.querySelector('#result').textContent = a + b
}

完整报错:

(输入 6 和 3,点 + 显示:63)

逐行分析:错在第 2~3 行——读 value 时没套 Number(),a 和 b 是字符串 '6' 和 '3';第 4 行的 + 一看两边都是字符串,切换成"拼接模式",输出 63。没有报错、没有警告,只有结果不对——这种翻车要靠"咦,怎么不对劲"的直觉发现。

正确写法:

let a = Number(document.querySelector('#a').value)
let b = Number(document.querySelector('#b').value)
document.querySelector('#result').textContent = a + b

翻车二:onclick 里函数名打错,一点就报错

<button onclick='calcc(\'+\')'>+</button>
function calc(op) {
  // ...
}

完整报错:

Uncaught ReferenceError: calcc is not defined
    at HTMLButtonElement.onclick

逐行分析:错在 HTML 的 onclick 属性——写的是 calcc,而 JS 里定义的是 calc。定义在页面加载时不会报错,直到你点按钮,浏览器去找 calcc 才发现查无此人。教训:onclick 属性里的函数名也是"名字引用",拼错一样会炸,而且是点击时才炸。

正确写法:

<button onclick='calc(\'+\')'>+</button>

翻车三:data-op 拼错,四个按钮集体变除法

<button data-opp='+' onclick='calc(this.dataset.op)'>+</button>
<button data-opp='*' onclick='calc(this.dataset.op)'>×</button>

完整报错:

(点 + 显示 2,点 × 也显示 2——全部变成 6 ÷ 3)

逐行分析:错在 HTML 的 data-opp——多了个 p,而 JS 里读的是 this.dataset.op。属性对不上,op 拿到的是 undefined;进了 if/else 链后,undefined 和 '+'、'-'、'*' 都不相等,一路滑到最后的 else 分支——做了除法。所有按钮殊途同归变成 ÷,就是这个原因。

正确写法:

<button data-op='+' onclick='calc(this.dataset.op)'>+</button>
<button data-op='*' onclick='calc(this.dataset.op)'>×</button>

📦 完整小示例

毕业作品再加一件:"青蛙体检处"——输入身高体重,一键算出 BMI 和体检评语。读取、计算、显示三步 + if/else 分支,综合章的知识点一个不落:

<h3>🐸 青蛙体检处</h3>
<p>
  身高 <input id='h' type='number' value='170'> 厘米
  体重 <input id='w' type='number' value='60'> 公斤
</p>
<button onclick='check()'>开始体检</button>
<p>体检报告:<b id='report'>等你点击</b></p>
<script>
  function check() {
    let h = Number(document.querySelector('#h').value)
    let w = Number(document.querySelector('#w').value)
    let hm = h / 100
    let bmi = w / (hm * hm)
    let result = 'BMI 是 ' + bmi
    if (bmi < 18.5) {
      result = result + ',偏瘦,多吃点害虫'
    } else if (bmi < 24) {
      result = result + ',标准,呱呱叫!'
    } else {
      result = result + ',偏胖,少喝水池奶茶'
    }
    document.querySelector('#report').textContent = result
  }
</script>

你会看到:输入 170 和 60 点按钮,报告显示“BMI 是 20.761245674740486,标准,呱呱叫!”;改成 160 和 45 显示“……偏瘦,多吃点害虫”;改成 170 和 90 显示“……偏胖,少喝水池奶茶”。小数后面拖一长串是电脑算除法的真实精度,属正常现象。

逐段中文精讲

  • 第 1~5 行(搭台):两个 type='number' 输入框各带 id 和默认值——和计算器同款套路,按钮负责点火。
  • 第 9~12 行(读取 + 准备):两行 Number(...value) 把输入转成真数字;hm 把厘米换算成米;bmi = 体重 ÷ 身高²,(hm * hm) 就是平方——只用乘除,没引入新知识。
  • 第 13 行(开场白):先把“BMI 是 xx”存进 result,后面分支只负责追加评语——先打底再加工,比每个分支重写整句更干净。
  • 第 14~20 行(分支评语):if / else if / else 三岔路口:小于 18.5 偏瘦、小于 24 标准、其余偏胖。注意顺序很重要——先拦住小的,剩下的自然落在后面。
  • 第 22 行(显示):textContent 把报告写回页面——读取、计算、显示三步走完,一个功能闭环。

跑通后做个小实验:把身高改成 0 点“开始体检”,看看会得到什么(提示:除以 0);再仿照计算器的 b === 0 分支,给体检处也加一道“身高不能为 0”的把关——把两个作品都磨成“打不坏的”。

🎯 什么时候用它

  • 任何“算一下”的小工具:房贷计算器、汇率换算、尾号限行查询——全是“读输入 → 计算 → 写回”三步,和本章的计算器、体检处同一个模子。
  • 注册/登录表单校验:点提交后检查“密码够不够 8 位、两次输入是否一致”,不合格就红字提示——把 if/else 链用在把关上,拦住错误输入。
  • 后台数据的可视化页面:拿到订单列表算总额、按状态分叉显示“待发货/已发货”——真实前端项目里,本章这套“变量存数据、函数做逻辑、DOM 展示、事件驱动”的组合拳天天在打。

📝 本章小结

  • 所有交互页面都是三步:读取 → 计算 → 显示;计算器只是这三步的排列组合。
  • 输入框的 value 永远是字符串,计算前必须 Number() 转型,否则 + 会拼接('6' + '3' = '63')。
  • + 有拼接/相加双重人格,- * / 会强制转数字;别赌它,先转型。
  • 除以 0 得 Infinity,空串转数字是 0——边界输入要自己用 if 把关。
  • 记忆锚点:交互页面是台自动贩卖机——投币(输入)、内部算账(计算)、掉出饮料(显示);哪一步卡了,就顺着“读、算、写”三步去查。

动手改

  1. 加一个"取余"按钮:data-op='%',JS 里加一个分支算 a % b(余数)
  2. 加一个"清零"按钮,一键清空两个输入框和结果
  3. 输入框留空时给个提醒:提示 Number('') 是 0,可以先判断 value === '' 再计算

JavaScript 毕业 🎉 前端三件套就绪,去 AI 板块 或 Python 板块 继续进阶

📥 下载本章代码

ZIP 内含本章全部代码文件与说明,解压即用,与教程内容同步生成。