見多識廣:JavaScript中的錯誤類型,別再一臉沒見過bug的樣子

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指定的範圍呀。

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,因爲它存在於環境記錄中只是它的值尚未設置。

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

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,因爲它操作的數據類型錯誤。

URIError

這說明了使用一種全局URI處理功能與其定義不兼容。

JS中的URI(統一資源指示符)具有以下功能:decodeURI,decodeURIComponent等。

如果我們用錯誤的參數調用其中任何一個,我們將得到一個URIError:

decodeURI("%")
^

URIError: URI malformed

encodeURI,獲取URI的未編碼版本。“%”不是正確的URI,因此引發了URIError。

EvalError

如果非法調用 eval(),則拋出 EvalError 異常。

根據EcmaSpec 2018版:

此異常不再會被JavaScript拋出,但是EvalError對象仍然保持兼容性。

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()
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章