在IE10中已經新加入了Error.stack 的支持,可以加快開發人員的腳本調試,並更正錯誤。尤其是一些難以重現的錯誤,如異步操作等。以下內容來自於微軟IE團隊,對於這個特性描述的非常詳細。
調試應用程序JavaScript 中的結構化錯誤處理依賴於 throw
和 try/catch
,開發人員將在其中聲明一個錯誤,並將控制流傳遞至處理錯誤的程序的某一部分。當某一錯誤被引發時,Chakra,即 Internet Explorer 中的 JavaScript 引擎將捕獲引發該錯誤的調用鏈,這一過程也被稱為調用堆棧。如果被引發的對象是一個Error
(或者是一個函數,且其原型鏈將導致 Error
),那麼 Chakra 將創建一個堆棧跟蹤,即可人工讀取的調用堆棧列表。該列表將被表示為一種屬性,即 Error
對象中的 stack
。stack
包含錯誤消息、函數名稱和該函數的源文件位置信息。這些信息將有助於開發人員了解所調用的函數,甚至查看錯誤的代碼行,從而迅速診斷缺陷。例如,這些信息可能表明傳遞至函數的某一參數為空,或為無效類型。
讓我們一同來查看一個簡單的腳本,並以此展開深入討論。該腳本試圖計算 (0, 2)
和 (12, 10)
兩點間的距離:
pointDistance
函數將返回錯誤的結果;而在其他情況中,該腳本將導致錯誤發生。為了理解堆棧跟蹤的含義,讓我們一同來查看 F12 開發人員工具中的錯誤,並查看其腳本選項卡:
堆棧跟蹤將轉儲至 catch
子句中的控制台,由於其位於堆棧的頂部,因此起源於 squareRoot
函數的錯誤將變得顯而易見。為了調試這一問題,開發人員無需深入查看堆棧跟蹤;系統已違反squareRoot
的前置條件,而且只需查看堆棧的上一級,原因將變得十分明了:squareRoot
調用內的子表達式自身應該為 square
的參數。
調試過程中,stack
屬性將有助於識別用於設置斷點的代碼。請記住:您還可使用其它方法來查看調用堆棧:例如,如果您將腳本調試程序設置為“捕獲異常即中斷”的模式,那麼您可使用該調試程序來檢查調用堆棧。對於部署的應用程序,您可考慮在 try/catch
內合並問題代碼,以捕獲失敗的調用,並將其記錄於服務器中。隨後,開發人員可查看調用堆棧,以隔離問題區域。
此前,我曾注意到被引發的對象必須為 Error
或通過其原型鏈導致 Error
。這是有意而為之;JavaScript 可支持引發任何對象,甚至包括作為異常的基元。盡管系統可捕獲和檢查所有這些對象,但是它們的全部用途並非包含錯誤或診斷信息。因此,引發過程中僅將更新錯誤的 stack
屬性。
即便對象為 DOM 異常,它們也不包含可導致 Error
的原型鏈,因此它們將不包含 stack
屬性。在某些應用場景中,您需要執行 DOM 操作,並希望暴露 JavaScript 兼容的錯誤,那麼您可能希望在try/catch
數據塊內合並您的 DOM 操作代碼,並在 catch
子句中引發一個新的 Error
對象:
Error
可能是我們需要選擇的正確方式。
性能注意事項
堆棧跟蹤的構造始於錯誤對象被引發之時;構造堆棧跟蹤需要查看當前執行堆棧。為了防止遍歷特大堆棧過程中出現性能問題(甚至可能出現的遞歸堆棧鏈),默認情況下,IE 僅將收集前十位的堆棧幀。然而該設置可通過將靜態屬性 Error.stackTraceLimit
設置為另一數值而得以配置。該設置是全局性的,而且必須在引發錯誤之前 進行變更,否則其將對堆棧跟蹤無效。
當某一堆棧是由異步回調(例如 timeout
、interval
或 XMLHttpRequest
)生成,那麼異步回調(而非由異步回調創建的代碼)將位於調用堆棧的底部。這將對跟蹤有問題的代碼產生某些潛在影響:如果您對多個異步回調使用相同的回調函數,那麼您將難於通過單獨檢查而確定是哪一回調產生了錯誤。讓我們對此前的示例稍作修改,我們將避免直接調用 sample()
,而是將其放入超時回調:
,而是Anonymous function
。事實上,這並非同一匿名函數,而是傳遞至 setTimeout
的回調函數。由於您丟失了與掛起回調有關的上下文,因此您可能無法確定調用回調的內容。如果在某一應用場景中,系統注冊了某一回調來處理許多不同按鈕的 click
事件,那麼您將無法分辨注冊將引用哪一回調。話雖如此,這一限制作用畢竟有限,因為在大多數情況中,堆棧頂部可能將突出顯示問題區域。
觀看體驗演示
了解 Windows 8 Consumer Preview 中 IE10 的使用情況。您可在 eval
的上下文中執行代碼,如果發生錯誤,您便可檢查出該錯誤。如果您在 IE10 內運行代碼,由於您可將錯誤代碼行懸停於堆棧跟蹤中,因此您也可突出顯示您的代碼行。您可自行將代碼輸入到代碼區域,或者從列表中的數個示例中進行選擇。此外,您還可在運行代碼示例時設置 Error.stackTraceLimit
值。
如欲查看參考材料,請浏覽有關 Error.stack
和 stackTraceLimit
的 MSDN 文檔。