錯誤處理(Error Handling)
try / catch / finally
try {
// 可能出錯的程式碼
let data = JSON.parse("不是 JSON"); // ← 會拋出 SyntaxError
} catch (error) {
// 錯誤發生時執行
console.error("類型:", error.name); // ← "SyntaxError"
console.error("訊息:", error.message); // ← "Unexpected token..."
console.error("堆疊:", error.stack); // ← 詳細的錯誤位置
} finally {
// 不管有沒有錯都會執行
console.log("結束");
}
常見錯誤類型
// ReferenceError — 使用未宣告的變數
console.log(x); // ReferenceError: x is not defined
// TypeError — 對錯誤的型態做操作
null.name; // TypeError: Cannot read property 'name' of null
(123).toUpperCase(); // TypeError: 123.toUpperCase is not a function
// SyntaxError — 語法錯誤
JSON.parse("{ bad }"); // SyntaxError
// RangeError — 超出範圍
new Array(-1); // RangeError: Invalid array length
自訂錯誤
// 自訂 Error 類別
class ValidationError extends Error {
constructor(field, message) {
super(message); // ← 呼叫父類
this.name = "ValidationError";
this.field = field; // ← 自訂屬性
}
}
// 拋出自訂錯誤
function validateAge(age) {
if (typeof age !== "number") {
throw new ValidationError("age", "年齡必須是數字");
}
if (age < 0 || age > 150) {
throw new ValidationError("age", "年齡必須在 0~150 之間");
}
return true;
}
// 捕捉
try {
validateAge("abc");
} catch (error) {
if (error instanceof ValidationError) {
console.log(`欄位 ${error.field} 錯誤:${error.message}`);
} else {
throw error; // ← 不認識的錯誤重新拋出
}
}
async 函式的錯誤處理
// 方式 1:try/catch
async function fetchUser(id) {
try {
let response = await fetch(`/api/users/${id}`);
if (!response.ok) throw new Error(`HTTP ${response.status}`);
return await response.json();
} catch (error) {
console.error("取得使用者失敗:", error);
return null; // ← 回傳預設值
}
}
// 方式 2:.catch()
let user = await fetchUser(1).catch(err => {
console.error(err);
return null;
});
全域錯誤處理
// 捕捉未處理的錯誤
window.addEventListener("error", (event) => {
console.error("未捕捉的錯誤:", event.error);
// 可以發送到錯誤追蹤服務
});
// 捕捉未處理的 Promise 拒絕
window.addEventListener("unhandledrejection", (event) => {
console.error("未處理的 Promise 拒絕:", event.reason);
event.preventDefault(); // ← 防止出現在 Console
});