综合练习:网页计算器
这是什么:综合实战 = 把变量、函数、DOM、事件全部拼起来,做一个真正能用的网页计算器。
为什么用:恭喜走到毕业章!这一章没有新知识——不把学过的全部拼起来,你只会写片段,不会写完整工具。
如何用:照着「读取 → 计算 → 显示」三步理清流程,再把完整代码贴进在线运行框点「▶ 运行」。
目标与思路
目标界面:两个数字输入框 + 加减乘除四个按钮 + 一行结果。
写之前先想清楚流程,任何交互页面都是这三步:
- 读取:拿到两个输入框里的数字
- 计算:按运算符算出结果
- 显示:把结果写回页面
完整代码
💡 代码可直接复制;想改、想跑,点右上「🧪 在线运行场」。
「你会看到」:点 + 显示 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 把关。 - 记忆锚点:交互页面是台自动贩卖机——投币(输入)、内部算账(计算)、掉出饮料(显示);哪一步卡了,就顺着“读、算、写”三步去查。
动手改
- 加一个"取余"按钮:
data-op='%',JS 里加一个分支算a % b(余数) - 加一个"清零"按钮,一键清空两个输入框和结果
- 输入框留空时给个提醒:提示
Number('')是 0,可以先判断value === ''再计算