正在加载...

JavaScript 错误

错误是函数拒绝继续的方式。本页使用没有 size 的 { drink: "tea" }。throw new Error("missing size") 立刻停下 label,停在 return 之前。catch 接到这个 Error。页面那一行读作 caught / missing size。

这不是调试那一课

上一页调用了 console.error("missing size"),然后返回一段备用文字。脚本继续往下走。没有抛出任何东西。console.error 不会抛出。
throw 不同。同一函数里它后面的行不会执行。只有 catch 能接过去。上一课调试那一行是 fixed / tea / regular。

Error 带有两段字符串

new Error("missing size") 创建一个对象。error.name 是 Error。error.message 是传入的文字,missing size。打印对象本身,不如打印这两个字段有用。

catch 接到 Error

缺少 size 时,label 会抛出。调用写在 try 里,所以 catch 会执行,并打印 error.message。文字是 missing size。

捕获缺少的尺寸

javascript
function label(order) {
if (!order.size) {
throw new Error("missing size");
}
return order.drink + " / " + order.size;
}
try {
console.log(label({ drink: "tea" }));
} catch (error) {
console.log(error.message);
}

日志是 missing size。label 从未走到 return,所以这里不会产生 tea / missing size。

完整订单会跳过 catch

把 size 设为 regular。label 正常返回。catch 不执行。

一份完整订单

javascript
function label(order) {
if (!order.size) {
throw new Error("missing size");
}
return order.drink + " / " + order.size;
}
try {
console.log(label({ drink: "tea", size: "regular" }));
} catch (error) {
console.log(error.message);
}

日志是 tea / regular。

finally 两条路都会走

调用成功时,finally 在 try 之后运行;抛出时,它在 catch 之后运行。把它留给两种情况都必须做的那一步。

throw 之后的 finally

javascript
function label(order) {
if (!order.size) {
throw new Error("missing size");
}
return order.drink + " / " + order.size;
}
try {
label({ drink: "tea" });
} catch (error) {
console.log(error.message);
} finally {
console.log("done");
}

日志先是 missing size,然后是 done。抛出之后,finally 写下 done。

读取名称和消息

捕获同一个 Error,把两个字段分行打印。

名称和消息

javascript
try {
throw new Error("missing size");
} catch (error) {
console.log(error.name);
console.log(error.message);
}

日志先是 Error,然后是 missing size。因此 error.name 是 Error,error.message 是 missing size。

检查函数抛出,调用方捕获

requireSize 知道规则。它抛出,并不组装标签。打印什么,由调用方决定。

把检查分开

javascript
function requireSize(order) {
if (!order.size) {
throw new Error("missing size");
}
}
try {
requireSize({ drink: "tea" });
console.log("ok");
} catch (error) {
console.log(error.message);
}

日志是 missing size。console.log("ok") 这一行不会执行,因为 requireSize 的抛出跳到了 catch。

杯子下面的那一行

页面调用 label 时没有尺寸。catch 用消息拼出可见的那一行。

页面演示 — 被捕获的错误

html
<!DOCTYPE html>
<html>
<body>
<p id="line">…</p>
<script>
function label(order) {
if (!order.size) {
throw new Error("missing size");
}
return order.drink + " / " + order.size;
}
let line = "";
try {
line = label({ drink: "tea" });
} catch (error) {
line = "caught / " + error.message;
}
document.getElementById("line").textContent = line;
</script>
</body>
</html>

那一行读作 caught / missing size。完整订单会返回 tea / regular,并让 catch 闲着。fixed / tea / regular 是调试那一页的行。

在柜台

  1. 在 try 里调用 label({ drink: "tea" })。catch 的日志是 missing size。
  2. 调用 label({ drink: "tea", size: "regular" })。日志是 tea / regular,catch 不执行。
  3. 在失败的调用外加上 finally。第二条日志是 done。
  4. 读取 error.name 和 error.message。日志是 Error 和 missing size。
  5. 读页面那一行:caught / missing size。

柜台上的疏漏

throw 会停下函数。console.error 不会抛出,也不会停下函数。

  • 以为 throw 后面的行还会执行
  • 忘掉 catch,让错误没人接
  • 以为 finally 只在成功之后运行
  • 把 error.message 读成名称 Error
  • 把那一行读成 fixed / tea / regular

记住这些

  • throw new Error("missing size") 在 return 之前停下 label
  • catch 接到 Error,并打印 error.message,内容是 missing size
  • 完整订单记下 tea / regular,并跳过 catch
  • 抛出之后,finally 写下 done
  • 页面那一行读作 caught / missing size

🧠 测试您的知识

准备开始

测试您的知识

通过这个互动测验挑战自己,看看你对这个主题的理解程度如何

❓
5
问题
🎯
70%
及格要求
♾️
∞
时间
🔄
∞
尝试次数

📝 说明

  • 仔细阅读每个问题
  • 为每个问题选择最佳答案
  • 您可以随时重新参加测验
  • 您的进度将显示在顶部