错误、try 与 catch
此页面需较新浏览器(支持 SharedArrayBuffer)。请升级 Chrome、Edge、Firefox 或 Safari 至最新版本。
错误会让程序停下
- JavaScript 无法执行某一行时,就会抛出一个错误,程序在那里停下。
- 错误信息写出错误的种类和出了什么问题。先读它,再改代码。
ReferenceError表示某个名字不存在,常常是拼错了。TypeError表示值的种类不对,比如调用一个不是函数的东西。
English
console.log("before");
let total = 5;
console.log(totl); // typo
console.log("after"); // never runs
Output:
before
ReferenceError: totl is not defined
try 和 catch
- 把有风险的代码放进
try { … }。 - 如果它抛出错误,程序会跳到
catch (err) { … },而不是停下。 err.message保存错误的文字。try…catch后面的代码无论如何都会运行。
English
try {
const data = JSON.parse("{ broken");
console.log(data);
} catch (err) {
console.log("Could not read the data");
}
console.log("still running");
// → Could not read the data
// → still running
用 throw 抛出自己的错误
throw new Error("message")让函数停下,并把错误交给调用它的地方。- 当函数拿到一个无法合理使用的值时就抛出错误。在能处理它的地方捕获它。
例题:安全的年龄检查
问题:checkAge(age) 在年龄小于 0 时应抛出错误,否则返回 "ok"。用两个年龄调用它,并报告每个结果。
function checkAge(age) {
if (age < 0) {
throw new Error("age cannot be negative");
}
return "ok";
}
for (const age of [12, -3]) {
try {
console.log(age, checkAge(age));
} catch (err) {
console.log(age, "rejected:", err.message);
}
}
// → 12 ok
// → -3 rejected: age cannot be negative
try…catch 放在循环里面,所以一个错误的年龄被报告后,循环仍然继续处理下一个。
注意
catch只捕获try块运行时抛出的错误。破坏整个程序语法的拼写错误永远不会被捕获。- 不要用空的
catch {}把所有错误藏起来。说明出了什么问题,否则 bug 就看不见了。
常见错误
- 写
throw "bad age"而不是throw new Error("bad age")。这样err.message是undefined。 - 把使用结果的
console.log放在try后面,那里已经访问不到try里面定义的变量。 - 捕获了错误,却当作值没有问题继续运行。要决定程序接下来该做什么。
现在轮到你
- 对错误的输入抛出错误,再捕获它并打印它的信息。
- 按检查答案来测试它。
难度 1/5 · 今日首次完成可获 100 金币及少量额外奖励
JSON.parse("oops") 会抛出错误。用 try…catch 包住它,让程序在 catch 中打印 bad data,然后在 try…catch 之后打印 done。
点击“运行”查看此处输出。
难度 2/5 · 今日首次完成可获 140 金币及少量额外奖励
编写 divide(a, b)。它返回 a / b,但当 b 为 0 时抛出 new Error("cannot divide by zero")。
点击“运行”查看此处输出。
难度 3/5 · 今日首次完成可获 200 金币及少量额外奖励
checkAge 已经写好。遍历 [20, -1, 7]。对每个年龄,checkAge 成功时打印 ok,抛出错误时打印错误的信息。
点击“运行”查看此处输出。