目錄
JavaScript 異常機制
1. 基本語法:try...catch...finally
2. 拋出異常:throw
3. 錯誤對象屬性
4. 同步代碼的異常處理
5. 異步代碼的異常處理
5.1 回調函數
5.2 Promise
5.3 全局未捕獲的 Promise 錯誤
6. 全局錯誤處理
7. 自定義錯誤與錯誤處理策略
8. 注意事項
9. 總結
JavaScript 嚴格模式與非嚴格模式
一、嚴格模式的核心特性
1.?啟用方式
二、嚴格模式 vs 非嚴格模式的關鍵差異
三、嚴格模式的優點
四、嚴格模式的應用場景
1.?避免全局污染
2.?安全的?this?綁定
3.?防止意外覆蓋只讀屬性
五、非嚴格模式的典型問題
1.?隱式創建全局變量
2.?危險的?eval?作用域
六、總結
JavaScript 異常機制
JavaScript 的異常處理機制允許開發者捕獲和處理運行時錯誤,確保程序在遇到意外情況時能夠優雅地降級或恢復。
1. 基本語法:try...catch...finally
-
try
?塊:包裹可能拋出錯誤的代碼。 -
catch
?塊:捕獲并處理?try
?塊中拋出的異常。 -
finally
?塊:無論是否發生異常,最終都會執行(常用于清理資源)。
try {// 可能出錯的代碼throw new Error("出錯了!");
} catch (error) {// 處理錯誤console.error("捕獲到錯誤:", error.message);
} finally {// 清理資源(如關閉文件、釋放內存)console.log("無論如何都會執行");
}
2. 拋出異常:throw
-
使用?
throw
?語句手動拋出錯誤,可拋出任意類型(但推薦使用?Error
?對象或其子類)。 -
內置錯誤類型:
-
Error
:通用錯誤基類。 -
SyntaxError
:語法錯誤(如 JSON 解析失敗)。 -
TypeError
:類型錯誤(如調用非函數)。 -
RangeError
:數值超出有效范圍(如遞歸過深)。 -
ReferenceError
:引用未聲明變量。 -
URIError
:URI 處理函數使用不當。 -
AggregateError
:多個錯誤的集合(如?Promise.any
?全部拒絕)。
-
// 拋出內置錯誤
throw new TypeError("變量類型錯誤");// 自定義錯誤
class NetworkError extends Error {constructor(message) {super(message);this.name = "NetworkError";}
}
throw new NetworkError("網絡請求失敗");
3. 錯誤對象屬性
-
name
:錯誤類型(如?"Error"
,?"TypeError"
)。 -
message
:錯誤描述信息。 -
stack
(非標準但廣泛支持):錯誤的調用棧跟蹤。
try {throw new Error("測試錯誤");
} catch (error) {console.log(error.name); // "Error"console.log(error.message); // "測試錯誤"console.log(error.stack); // 堆棧跟蹤信息
}
4. 同步代碼的異常處理
-
同步錯誤:在?
try
?塊中直接拋出,由?catch
?捕獲。 -
示例:
function divide(a, b) {if (b === 0) throw new Error("除數不能為零");return a / b; }try {divide(10, 0); } catch (error) {console.error(error.message); // "除數不能為零" }
5. 異步代碼的異常處理
5.1 回調函數
-
錯誤優先回調:Node.js 約定回調函數的第一個參數為錯誤對象。
const fs = require('fs'); fs.readFile('file.txt', (err, data) => {if (err) {console.error("讀取文件失敗:", err.message);return;}console.log(data); });
5.2 Promise
-
.catch()
:捕獲 Promise 鏈中的錯誤。 -
async/await
:結合?try...catch
?處理異步錯誤。// Promise.catch() fetch('https://api.example.com/data').then(response => response.json()).catch(error => console.error("請求失敗:", error));// async/await + try...catch async function fetchData() {try {const response = await fetch('https://api.example.com/data');const data = await response.json();return data;} catch (error) {console.error("請求失敗:", error);} }
5.3 全局未捕獲的 Promise 錯誤
-
瀏覽器:監聽?
unhandledrejection
?事件。 -
Node.js:監聽?
unhandledRejection
?事件。// 瀏覽器 window.addEventListener('unhandledrejection', event => {console.error("未處理的 Promise 錯誤:", event.reason); });// Node.js process.on('unhandledRejection', (reason, promise) => {console.error("未處理的 Promise 錯誤:", reason); });
6. 全局錯誤處理
-
瀏覽器:
window.onerror
?或?window.addEventListener('error')
。 -
Node.js:
process.on('uncaughtException')
。// 瀏覽器全局錯誤捕獲 window.onerror = (message, source, lineno, colno, error) => {console.error("全局錯誤:", message, "發生在", source, "行號:", lineno); };// Node.js 全局錯誤捕獲 process.on('uncaughtException', (error) => {console.error("未捕獲的異常:", error);process.exit(1); // 通常建議終止進程 });
7. 自定義錯誤與錯誤處理策略
-
自定義錯誤類:繼承?
Error
?以區分錯誤類型。 -
條件捕獲:在?
catch
?塊中根據錯誤類型處理。class ValidationError extends Error {constructor(field, message) {super(message);this.name = "ValidationError";this.field = field;} }try {throw new ValidationError("email", "郵箱格式無效"); } catch (error) {if (error instanceof ValidationError) {console.error(`字段 ${error.field} 驗證失敗: ${error.message}`);} else {console.error("其他錯誤:", error);} }
8. 注意事項
-
避免過度使用異常:異常適用于意外情況,而非控制流程。
-
資源清理:在?
finally
?或?try...catch
?外釋放資源(如關閉數據庫連接)。 -
錯誤日志:記錄錯誤信息(如?
console.error
、日志服務)。 -
錯誤傳播:在無法處理錯誤時重新拋出(
throw error
)。 -
性能考量:頻繁拋出異常可能影響性能,需謹慎使用。
9. 總結
機制 | 場景 | 工具/語法 | 注意事項 |
---|---|---|---|
同步錯誤處理 | 函數內直接拋出錯誤 | try...catch...finally | 處理意外情況,避免流程控制 |
異步錯誤處理 | Promise、回調函數、async/await | .catch() 、try...catch | 避免未處理的 Promise 拒絕 |
全局錯誤捕獲 | 未被捕獲的運行時錯誤 | window.onerror 、process.on | 記錄日志并終止不穩定進程 |
自定義錯誤 | 區分業務錯誤類型 | 繼承?Error ?類 | 提供清晰的錯誤分類和信息 |
? ?
JavaScript 嚴格模式與非嚴格模式
JavaScript 的?嚴格模式(Strict Mode)?是 ES5 引入的一種受限的代碼執行環境,旨在消除代碼中的靜默錯誤、提高安全性,并為未來版本鋪路。
一、嚴格模式的核心特性
1.?啟用方式
-
全局啟用:在腳本或函數頂部添加?
"use strict";
"use strict"; // 整個腳本進入嚴格模式
-
函數級啟用:在函數體頂部添加?
"use strict";
function strictFunc() {"use strict";// 該函數內部為嚴格模式 }
二、嚴格模式 vs 非嚴格模式的關鍵差異
特性 | 非嚴格模式 | 嚴格模式 | 示例與說明 |
---|---|---|---|
未聲明變量賦值 | 自動創建全局變量 | 拋出?ReferenceError | x = 10; ?→ 嚴格模式下報錯,防止全局污染 |
刪除不可刪除的屬性 | 靜默失敗 | 拋出?TypeError | delete Object.prototype; ?→ 嚴格模式下報錯 |
重復的函數參數 | 允許重復參數名 | 拋出?SyntaxError | function(a, a) {} ?→ 嚴格模式下語法錯誤 |
八進制字面量 | 允許?0123 ?表示八進制 | 必須使用?0o123 | const num = 0123; ?→ 嚴格模式下報錯,改用?0o123 |
eval ?和?arguments | 可被重新賦值 | 視為關鍵字,不可賦值 | eval = 10; ?→ 嚴格模式下報錯 |
with ?語句 | 允許使用 | 拋出?SyntaxError | with(obj) { ... } ?→ 嚴格模式下語法錯誤 |
this ?默認綁定 | 全局對象(window ) | undefined | function f() { console.log(this); } f(); ?→ 嚴格模式輸出?undefined |
arguments.callee | 可用 | 拋出?TypeError | function f() { return arguments.callee; } ?→ 嚴格模式下報錯 |
對象字面量重復屬性 | 允許重復屬性名(后者覆蓋前者) | 拋出?SyntaxError | const obj = { a: 1, a: 2 }; ?→ 嚴格模式下語法錯誤 |
三、嚴格模式的優點
-
更早暴露錯誤:將靜默錯誤轉為顯式拋出(如未聲明變量)。
-
優化代碼安全性:防止意外全局變量、限制危險操作(如?
eval
)。 -
優化引擎性能:減少歧義代碼,便于編譯器優化。
-
未來兼容性:避免使用未來可能成為語法的保留字(如?
interface
、let
)。
四、嚴格模式的應用場景
1.?避免全局污染
"use strict";
function init() {count = 10; // ReferenceError: count is not defined
}
init();
2.?安全的?this
?綁定
"use strict";
function logThis() {console.log(this); // undefined(非嚴格模式為 window)
}
logThis();
3.?防止意外覆蓋只讀屬性
"use strict";
const obj = {};
Object.defineProperty(obj, 'readOnly', { value: 42, writable: false });
obj.readOnly = 100; // TypeError: Cannot assign to read only property
五、非嚴格模式的典型問題
1.?隱式創建全局變量
function leak() {x = 10; // 非嚴格模式下自動成為 window.x
}
leak();
console.log(window.x); // 10
2.?危險的?eval
?作用域
var x = 10;
function test() {eval('var x = 20;'); // 非嚴格模式下修改局部變量console.log(x); // 20(嚴格模式下輸出 10)
}
test();
eval()
?函數會將傳入的字符串當做 JavaScript 代碼進行執行。?
六、總結
決策因素 | 非嚴格模式 | 嚴格模式 |
---|---|---|
代碼安全性 | 低(隱式錯誤多) | 高(顯式錯誤提示) |
兼容性 | 兼容舊代碼 | 需注意 ES3 特性差異 |
開發體驗 | 靈活但易出錯 | 規范且易維護 |
未來兼容性 | 可能逐漸淘汰 | 符合現代標準 |
建議:所有新項目默認啟用嚴格模式,舊項目逐步遷移。通過?"use strict";
?提升代碼質量,減少潛在 Bug。