学完 Python 的异常处理(捕获异常、自定义异常、手动抛出、异常传递)后,对照 JavaScript 中的对应知识点,梳理异同,加深理解。
一、异常捕获:try-except vs try-catch
Python 使用 try-except,JavaScript 使用 try-catch。核心差异在于 Python 支持多分支分类捕获和 else 子句。
py
# Python:支持多个 except 分支 + else
try:
result = 10 / 0
except ZeroDivisionError:
print("除数不能为零!")
except ValueError:
print("值错误!")
except Exception as e:
print(f"其他错误: {e}")
else:
print("没有异常时执行") # JS 没有这个
finally:
print("无论如何都执行")
js
// JavaScript:只有一个 catch 块,需手动判断类型
try {
const result = 10 / 0;
} catch (error) {
if (error instanceof RangeError) {
console.log("范围错误");
} else {
console.log("其他错误:", error.message);
}
} finally {
console.log("无论如何都执行");
}
关键差异 :Python 的 except 可以写多个分支精确匹配异常类型;JS 只有一个 catch,需要手动用 instanceof 判断。Python 独有的 else 子句在 try 块无异常时执行。
二、自定义异常类
Python 继承 Exception,JavaScript 继承 Error,写法高度相似。
python
# Python
class UserNotFoundError(Exception):
def __init__(self, message):
super().__init__(message)
javascript
// JavaScript
class UserNotFoundError extends Error {
constructor(message) {
super(message);
this.name = "UserNotFoundError";
}
}
差异 :Python 的异常继承体系更丰富(BaseException → Exception → 各种具体异常),日常捕获推荐用 Exception 而非 BaseException(后者包含 SystemExit、KeyboardInterrupt 等系统级异常)。JS 的 Error 子类相对较少(TypeError、RangeError、ReferenceError 等)。
三、手动抛出异常:raise vs throw
Python 用 raise,JavaScript 用 throw,功能等价。
py
# Python
raise ValueError("年龄不能小于 0")
js
// JavaScript
throw new Error("年龄不能小于 0");
差异 :Python 的 raise 可以不传参数,在 except 块中直接 raise 即可重新抛出当前异常 ;JS 的 throw 必须指定一个值,且 JS 允许 throw 任意类型的值(字符串、数字等),而 Python 的 raise 只能抛出 BaseException 的子类。
四、异常的传递机制
两者机制完全一致:异常沿调用栈向上传递,直到被捕获或程序终止。
py
# Python 示例
def funA():
num = 1 / 0 # 抛出 ZeroDivisionError
def funB():
funA() # 没有 try,异常继续向上传递
def funC():
try:
funB()
except ZeroDivisionError as e:
print(f"在 funC 中捕获: {e}")
funC() # 输出: 在 funC 中捕获: division by zero
js
// JavaScript 示例(行为完全一致)
function funA() {
throw new Error("出错了");
}
function funB() {
funA(); // 异常继续向上传递
}
function funC() {
try {
funB();
} catch (error) {
console.log(`在 funC 中捕获: ${error.message}`);
}
}
funC(); // 输出: 在 funC 中捕获: 出错了
五、核心差异总结
| 特性 | Python | JavaScript |
|---|---|---|
| 捕获语法 | try / except / else / finally |
try / catch / finally |
| 多分支捕获 | 多个 except 分支 |
只有一个 catch,需手动判断 |
| 成功分支 | else 子句 |
无 |
| 抛出关键字 | raise |
throw |
| 异常基类 | Exception |
Error |
| 重新抛出 | raise(无参数即可) |
throw error(需显式传入) |
| 异常链 | raise ... from ... 语法 |
无原生支持 |
| 异步异常 | try/except 配合 async/await |
try/catch + async/await + Promise .catch() |
| 可抛出类型 | 仅限 BaseException 子类 |
任意值(字符串、数字等均可) |
六、JS 额外需要关注的点
1. 异步异常
JS 的 try-catch 只能捕获同步代码 的异常。异步代码(如 setTimeout、Promise)中的异常需要用 .catch() 或 async/await 配合 try-catch 来捕获。
js
// 这样捕获不到 setTimeout 里的异常
try {
setTimeout(() => {
throw new Error("异步错误");
}, 1000);
} catch (e) {
console.log("捕获不到"); // 不会执行
}
// 正确做法:async/await + try-catch
async function fetchData() {
try {
const res = await fetch("/api/data");
const data = await res.json();
} catch (error) {
console.log("捕获到异步错误:", error.message);
}
}
// 或者用 Promise.catch()
fetch("/api/data")
.then(res => res.json())
.catch(error => console.log("捕获到错误:", error.message));
2. 全局异常捕获
JS 有全局兜底机制,适合做统一的错误上报:
js
// 浏览器环境
window.onerror = function(message, source, lineno, colno, error) {
console.log("全局捕获:", error);
};
// 未处理的 Promise 异常
window.addEventListener("unhandledrejection", event => {
console.log("未处理的 Promise 异常:", event.reason);
});
// Node.js 环境
process.on("uncaughtException", error => {
console.log("未捕获的异常:", error);
});