学习前提

理解函数、异常和作用域;多文件示例需要本地HTTP服务。

本课完成后你能做什么

把计算和页面副作用分开,通过最小复现和断言定位错误。

先理解机制

ES模块通过export公开接口,import声明依赖,模块具有自己的作用域并使用严格模式。HTML使用script type=module加载;跨文件示例应通过HTTP服务访问,file协议下的模块加载常被浏览器限制。不要把生产密钥写到前端模块中。

先区分语法错误、运行异常与逻辑错误。阅读第一条相关报错及堆栈,复现一次,再在状态改变的位置打断点。观察实际参数、调用栈和网络响应比随意增加延时更有效。console.log用于观察,断言用于明确预期。

测试至少覆盖正常、边界、无效输入和历史回归。纯函数不依赖DOM、时间或网络,最容易重复验证。集成测试再检查表单输入到页面反馈的完整路径。下面先在单文件控制台测试,再拆成两个模块。

可运行示例

function percentage(done, total) {
  if (!Number.isInteger(done) || !Number.isInteger(total) || total < 0 || done < 0 || done > total) {
    throw new RangeError("Invalid progress");
  }
  return total === 0 ? 0 : Math.round(done / total * 100);
}
function assertEqual(actual, expected, label) {
  if (actual !== expected) throw new Error(`${label}: ${actual} !== ${expected}`);
}
assertEqual(percentage(1, 8), 13, "rounding");
assertEqual(percentage(0, 0), 0, "empty course");
assertEqual(percentage(8, 8), 100, "complete");
let rejected = false;
try { percentage(9, 8); } catch (error) { rejected = error instanceof RangeError; }
assertEqual(rejected, true, "invalid range");
console.log("4 checks passed");

推演与验证

应只显示4 checks passed。把Math.round改为Math.floor,rounding断言会失败;这证明测试能捕捉相关行为变化。修复后再验证,不要通过修改期望值掩盖错误。

常见错误与边界

只测试代码当前怎么写,容易漏掉需求。测试应说明期望规则,例如已完成数不得大于总数。随机测试若不能复现难以诊断,保留随机种子或失败输入。

动手练习

把percentage放到progress.js并导出,main.js导入;在HTML用模块脚本加载main.js。加入负数和小数测试。

参考解法与理由

progress.js仅保留导出函数;main.js负责断言或DOM。相对导入写完整路径 ./progress.js,检查Network请求和响应类型。生产打包工具不是理解模块的前提。

进一步阅读