JavaScript >> Javascript 文檔 >  >> Tags >> Error

拋出 JavaScript 錯誤的藝術

在我年輕的時候,編程語言中最令人困惑的部分是產生錯誤的能力。我對 throw 的第一反應 Java 中的運算符是,“那太愚蠢了,你為什麼要導致 一個錯誤?”錯誤是我的敵人,我試圖避免這種情況,因此導致錯誤的能力似乎是該語言無用且危險的方面。我認為在 JavaScript 中包含相同的運算符是愚蠢的,這是一種人們一開始並不理解的語言。現在有了豐富的經驗,我非常喜歡自己犯錯誤。如果做得好,這樣做可以更容易地進行調試和代碼維護。

編程時,當意外發生時會發生錯誤。可能將不正確的值傳遞給函數或數學運算具有無效的操作數。編程語言定義了一組基本規則,當偏離這些規則時,會導致錯誤,以便開發人員可以修復代碼。如果不拋出錯誤並報告給您,調試幾乎是不可能的。如果一切都無聲無息地失敗了,那麼您首先需要很長時間才能注意到存在問題,更不用說隔離和修復它了。錯誤是開發者的朋友,而不是敵人。

錯誤的問題在於它們往往會在意想不到的地方和意想不到的時間出現。更糟糕的是,默認錯誤消息通常過於簡潔,無法真正解釋問題所在。 JavaScript 錯誤消息是出了名的缺乏信息性和神秘性(尤其是在 Internet Explorer 中),這只會使問題更加複雜。想像一下,如果彈出一條錯誤消息,上面寫著“這個函數失敗了,因為這件事發生了”。立即,您的調試任務變得更容易。這就是自己拋出錯誤的好處。

將錯誤視為內置的失敗案例會有所幫助。在代碼中為特定點的故障做計劃總是比在任何地方預測故障更容易。這是產品設計中非常常見的做法,而不僅僅是代碼中。汽車製造時帶有壓皺區,即在受到衝擊時會以可預測的方式倒塌的框架區域。了解車架在碰撞中將如何反應,哪些部件會失效,使製造商能夠確保乘客的安全。你的代碼可以用同樣的方式構造。

儘管 JavaScript 在過去幾年中取得了長足的進步,但與其他語言的開發人員相比,JavaScript 開發人員仍然擁有更少的工具來幫助調試。由於調試困難,在 JavaScript 中拋出錯誤可以說比在任何其他語言中都更有價值。您可以使用 throw 拋出一個 運算符並提供要拋出的對象。可以拋出任何類型的對象,但是,Error object 是最典型的使用方法:

throw new Error("Something bad happened.")

當您以這種方式拋出錯誤時,錯誤不會通過 try-catch 捕獲 語句,瀏覽器將以瀏覽器的典型方式顯示錯誤文本。對於 Internet Explorer,這意味著瀏覽器左下角會顯示一個小圖標,雙擊該圖標會顯示一個帶有錯誤文本的對話框;安裝了 Firebug 的 Firefox 將在控制台中顯示錯誤; Safari 和 Chrome 將錯誤輸出到 Web Inspector; Opera 在錯誤控制台中顯示錯誤。換句話說,它被視為您沒有拋出的錯誤。

不同之處在於您可以提供瀏覽器要顯示的確切文本。您可以包含成功調試問題所需的任何信息,而不僅僅是行號和列號。我通常建議您始終在錯誤消息中包含函數名稱以及函數失敗的原因。考慮以下函數:

function addClass(element, className){
    element.className += " " + className;
}

這個函數的目的是為給定的元素添加一個新的 CSS 類(JavaScript 庫中非常常見的方法)。但是如果 elementnull ?您將收到一條神秘的錯誤消息,例如“預期對象”。然後,您需要查看執行堆棧(如果您的瀏覽器支持它)以實際定位問題的根源。通過拋出錯誤,調試變得容易得多:

function addClass(element, className){
    if (element != null && typeof element.className == "string"){
        element.className += " " + className;
    } else {
        throw new Error("addClass(): First arg must be a DOM element.");
    }
}

除了關於準確檢測對像是否為 DOM 元素的討論之外,此方法現在在由於無效 element 而失敗時提供更好的消息傳遞 爭論。在錯誤控制台中看到如此冗長的消息會立即導致您找到問題的根源。我喜歡把拋出錯誤看作是給自己留下便利貼,說明為什麼某事失敗了。

了解如何拋出錯誤只是等式的一部分;了解何時 拋出錯誤是另一個。由於 JavaScript 沒有類型或參數檢查,許多開發人員錯誤地認為他們應該為每個函數實現它。這樣做是不切實際的,並且會對整個腳本的性能產生不利影響。關鍵是識別可能以特定方式失敗的代碼部分,並且只在那裡拋出錯誤。簡而言之,只在已經發生錯誤的地方拋出錯誤。

如果一個函數只會被已知實體調用,則可能不需要錯誤檢查(私有函數就是這種情況);如果您無法提前確定將調用函數的所有位置,那麼您可能需要進行一些錯誤檢查,並且更有可能從拋出自己的錯誤中受益。拋出錯誤的最佳位置是實用程序函數,這些函數是腳本環境的一般部分,可以在任意數量的地方使用。 JavaScript 庫正是如此。

對於已知的錯誤情況,所有 JavaScript 庫都應從其公共接口中拋出錯誤。 YUI/jQuery/Dojo/等。無法預測您將在何時何地調用它們的函數。當你做愚蠢的事情時告訴你是他們的工作。為什麼?因為您不必調試他們的代碼來找出問題所在。錯誤的調用堆棧應該在庫的接口中終止,而不是更深。沒有什麼比看到庫中有 12 個函數的錯誤更糟糕的了。庫開發者有責任防止這種情況發生。

這也適用於私有 JavaScript 庫。許多 Web 應用程序都有自己的專有 JavaScript 庫,這些庫可以使用或代替眾所周知的公共選項構建。庫的目標是讓開發人員的生活更輕鬆,這是通過提供遠離臟實現細節的抽象來實現的。拋出錯誤有助於將那些骯髒的實現細節安全地隱藏在開發人員之外。

JavaScript 還提供了一個 try-catch 能夠在瀏覽器處理之前攔截拋出的錯誤的語句。通常情況下,開發人員很難判斷是否適合使用 try-catch 引發錯誤或捕獲錯誤 .錯誤應該只在應用程序堆棧的最深部分引發,如前所述,這通常意味著 JavaScript 庫。任何處理特定於應用程序邏輯的代碼都應該具有錯誤處理能力,因此應該能夠捕捉低級組件拋出的錯誤。

應用程序邏輯總是知道它為什麼調用一個特定的函數,因此最適合處理錯誤。值得一提的是,您永遠不應該擁有 try-catch catch 為空的語句 條款;您應該始終以某種方式處理錯誤。這在開發與生產中可能有所不同,但必須這樣做。如果發生錯誤,答案絕不應該是簡單地將其包裝在 try-catch 順其自然——這掩蓋了一個錯誤,而不是處理它。

在 JavaScript 中拋出錯誤是一門藝術。找出代碼的適當部分應該在哪裡引發錯誤需要時間。然而,一旦你弄清楚了這一點,你會發現你的調試時間會減少,你對代碼的滿意度也會提高。


Tutorial JavaScript 教程
  1. 綁定哪個鍵以避免與本機瀏覽器快捷方式衝突?

  2. 無法在 Javascript 中使用 setHours() 將時間設置為 00:00:00:00

  3. 我如何在 Angular 項目中使用 OpenAPI 規範

  4. 使用 GraphQL API 在 Next.js 中為內容豐富的博客文章分頁

  5. JavaScript 中 new String(x) 的意義何在?

  6. JS setInterval 只執行一次

  7. React GraphQL 入門

  1. 我需要你的幫助來整理課程。

  2. 使用 tinyMCE 設置文本區域的內容

  3. JavaScript 中的數組和數組方法

  4. 將 storybook.js 添加到 sveltekit 項目

  5. Addy Osmanis 18 點 Web 性能檢查表

  6. Javascript中的矢量圖形?

  7. 如何使用 LocalStack 在本地偽造 AWS

  1. 召喚 JSON 狀態更新

  2. 為什麼你應該選擇 TypeScript 而不是 JavaScript

  3. 使用 Gridsome 啟動您的個人寫作網站

  4. react-three-fiber:火星動畫🚀