7種你應該知道的JavaScript常見的錯誤
轉載請註明出處:葡萄城官網,葡萄城為開發者提供專業的開發工具、解決方案和服務,賦能開發者。
原文出處:https://blog.bitsrc.io/types-of-native-errors-in-javascript-you-must-know-b8238d40e492
從瀏覽器的控制檯到執行Node.js的計算機終端,我們到處都會看到各類錯誤。
這篇文章的重點是概述我們在JS開發過程中可能遇到的錯誤型別。
1. RangeError
當數字超出允許的值範圍時,將丟擲此錯誤。
例如,
const l = console.log const arr = [90,88] arr.length=90**99
我們有一個帶有兩個元素的arr。接下來,我們嘗試使陣列包含90**99 == 2.9512665430652753e+193
元素。
這個數字超出了大小陣列可以增長的範圍。所以執行時它會丟擲RangeError:
$ node errors errors.js:4 arr.length=90**99 ^ RangeError: Invalid array length
因為我們要增加arr陣列的數量超出了JS指定的範圍。
2. ReferenceError
當對變數/項的引用被破壞或不存在時,將引發此錯誤。也就是說,變數/項不存在。
例如,
const l=console.log const cat = "cat" cat dog
我們有一個變數cat初始化為“ cat”。接下來,我們引用cat變數和dog變數。cat變數存在,而dog變數不存在。
cat將返回“ cat”,而dog會引發ReferenceError,因為在環境記錄中找不到名為dog的變數。
$ node errors errors.js:3 dog ^ ReferenceError: dog is not defined
每當我們建立或定義變數時,變數名稱都會寫入環境記錄中。此環境記錄就像鍵值儲存表一樣,如下圖:
+-------------+ | Key | Value | --------------- | cat | "cat" | +-------------+
每當我們引用變數時,它都會儲存程式中定義的變數。當在記錄中找到環境值並提取並返回值時,將以該變數的名稱作為關鍵字搜尋環境記錄。呼叫尚未定義的函式。
現在,當我們建立或定義一個沒有賦值的變數時。變數將鍵作為變數名寫入環境記錄,但該值將保持未定義狀態。
var cat env record +-----------------+ | Key | Value | ------------------- | cat | undefined | +-----------------+
稍後為變數分配值時,將在env記錄中搜索該變數,當發現該初始未定義值時,該賦值將被覆蓋。
var cat cat = "cat" env record +-------------+ | Key | Value | --------------- | cat | "cat" | +-------------+
因此,當在env記錄中找不到變數名時,JS引擎會丟擲RefernceError。
+-------------+ | Key | Value | --------------- | cat | "cat" | +-------------+ cat // "cat", yes, :) it's there dog // :( what's this? can't find it
注意:未定義的變數不會丟擲ReferenceError,因為它存在於環境記錄中只是它的值尚未設定。
3. SyntaxError
這是我們遇到的最常見的錯誤。當我們鍵入JS引擎難以理解的程式碼時,會出現此錯誤。解析期間,JS引擎捕獲了此錯誤。
在JS引擎中,我們的程式碼經歷了不同的階段,然後才能在終端上看到執行結果。
- 標記化
- 解析
- 執行
標記化將原始碼分解為各個單元。在這個階段,將對數字,關鍵字,文字,運算子進行分類並分別進行標記。接下來,生成的token流將傳遞到解析階段,由解析器處理。這是從token生成AST的地方。AST是我們程式碼結構的抽象資料結構。
在標記化和解析這兩個階段,如果我們程式碼的語法不符合JS的語法規則,則會使執行階段失敗並引發SyntaxError。例如,
const l = console.log let cat h =“ cat”
這裡的“h”明顯是多餘的,所以由於多了這個字元,會導致引擎丟擲SyntaxError
$ node errors errors.js:3 let cat h = "cat" ^ SyntaxError: Unexpected identifier
很顯然,Node.js引擎發現了錯誤,由於這個不和諧字元的出現,導致cat變數的宣告失敗了。
4. TypeError
TypeError 是指物件用來表示值的型別非預期型別時發生的錯誤。例如,我們期望它是布林值,但結果發現它是string型別。
再例如:
const num = 123 num.toUpperCase()
這會引發TypeError
$ node errors
errors.js:4
num.toUpperCase()
^
TypeError: num.toUpperCase is not a function
因為toUpperCase函式需要字串資料型別。toUpperCase函式是有意通用的;它不需要其this值是String物件。因此,可以將其轉移到其他種類的物件中用作方法。
如果我們在Objects,Boolean,Symbol,null,undefined資料型別上呼叫toUpperCase函式,則只有字串會轉換為大寫或小寫形式,我們將得到TypeError,因為它操作的資料型別錯誤。
5. URIError
這說明了使用一種全域性URI處理功能與其定義不相容。
JS中的URI(統一資源指示符)具有以下功能:decodeURI,decodeURIComponent等。
如果我們用錯誤的引數呼叫其中任何一個,我們將得到一個URIError。
decodeURI("%") ^ URIError: URI malformed
encodeURI,獲取URI的未編碼版本。“%”不是正確的URI,因此引發了URIError。
編碼或解碼URI時出現問題時,將引發URIError。
6. EvalError
如果非法呼叫 eval(),則丟擲 EvalError 異常。
根據EcmaSpec 2018版:
此異常不再會被JavaScript丟擲,但是EvalError物件仍然保持相容性。
7. InternalError
該錯誤在JS引擎內部發生,特別是當它有太多資料要處理並且堆疊增長超過其關鍵限制時。
當JS引擎被太多的遞迴,太多的切換情況等淹沒時,就會發生這種情況
switch(num) { case 1: ... break case 2: ... break case 3: ... break case 4: ... break case 5: ... break case 6: ... break case 7: ... break ... up to 1000 cases }
太多的遞迴,一個簡單的例子是這樣的:
function foo() { foo() } foo()
結論
正如我們所說,沒有人能不犯錯誤。就我們輸入的程式碼而言,發生錯誤是難以避免的。不過為了避免更多的錯誤出現,我們需要知道丟擲的錯誤的型別是什麼,我們該如何解決。
所以我們在這篇文章中列出了它們,並提供了一些示例來簡要的來介紹了它們是如何發生的。
最後,希望本文的一些淺見能為你寫出更好的程式碼提供一些幫助,謝謝!
&n