如何修復那些奇怪的 JavaScript 錯誤

發表於2015-07-19

除錯 JavaScript 也許是一場噩夢:一些錯誤非常難理解,並且給出的錯誤行號並不是總是很有幫助。如果有一個列表,列舉這些錯誤的意思和如何修復它們,將對我們非常有幫助。

本文列舉了 JavaScript 中一些奇怪的錯誤。對於相同的錯誤不同的瀏覽器可能給出不同的提示,所以分別給出了不同的例子。

如何閱讀錯誤

進入正題之前,我們先快速分析一下錯誤訊息的結構,這對我們理解錯誤訊息非常有用,同時也將有助於你理解那些沒有在本文中列舉的錯誤。

Chrome 中一個典型的錯誤看起來像這樣:

Uncaught TypeError: undefined is not a function

該錯誤的結構如下:

  1. Uncaught TypeError: 該部分並不是很有用。Uncaught 表示該錯誤沒有被 catch 語句捕獲,TypeError 是錯誤名。
  2. undefined is not a function: 是訊息體,需要從字面上理解。例如本例中,它的字面意思是,程式碼嘗試將 undefined 當作函式使用。

其他基於 webkit 的瀏覽器,比如 Safari,錯誤訊息與 Chrome 基本一樣。Firefox 的錯誤訊息與上面非常相似,但並不總是都包含第一部分,最近版本的 IE 的錯誤訊息也比 Chrome 的簡單,但在這裡,更簡單並不意味著更好。

下面看看我們經常會遇到的一些錯誤。

Uncaught TypeError: undefined is not a function

同類錯誤:

  • number is not a function
  • object is not a function
  • string is not a function
  • Unhandled Error: ‘foo’ is not a function
  • Function Expected

嘗試將一個值(value)當作函式使用,但該值並不是一個函式。例如:

這個錯誤很常見,當呼叫物件中的一個方法,但寫錯了方法名:

訪問物件中不存在的屬性時將返回 undefined,上面程式碼就將出現該錯誤。

其他類似的錯誤,比如“number is not a function”發生在嘗試將一個 Number 當作函式使用時。

如何修復:確保函式名正確。對於該錯誤,行號通常準確地指向了錯誤發生的位置。

Uncaught ReferenceError: Invalid left-hand side in assignment

同類錯誤:

  • Uncaught exception: ReferenceError: Cannot assign to ‘functionCall()’
  • Uncaught exception: ReferenceError: Cannot assign to ‘this’

當嘗試給一個不能被賦值的變數賦值時將發生該錯誤。看下面的典型例子:

在上面例子中,開發人員不小心將 == 寫成了 =,錯誤訊息“left-hand side in assignment”指等號左邊包含不能被賦值的變數。

如何修復:確保不給函式函式的返回值或 this 關鍵字賦值。

Uncaught TypeError: Converting circular structure to JSON

同類錯誤:

  • Uncaught exception: TypeError: JSON.stringify: Not an acyclic Object
  • TypeError: cyclic object value
  • Circular reference in value argument not supported

該錯誤總是發生在使用 JSON.stringify 序列化一個存在迴圈引用的物件時。

由於上面 a 和 b 兩個物件都彼此相互引用,結果導致物件不能被轉換為 JSON 字串。

如何修復:移除將要被轉換為 JSON 字串物件內部的迴圈引用。

Unexpected token ;

同類錯誤:

  • Expected )
  • missing ) after argument list

通常發生在缺少括號或分號時。

該錯誤中所謂的符號(token)可以多種多樣,如“Unexpected token ]”或“Expected {”等等。

如何修復:該錯誤提示的行號有時並不能指向正確的位置,這增加了修復難度。

  • 錯誤資訊中包含“[ ] { } ( )”時,通常是因為缺少配對的部分,檢查所有括號,保證都是配對的。這種情況下,行號通常指向了其他位置,問不是錯誤的位置。
  • 異常的 / 和正規表示式有關,行號指向了正確的位置。
  • 異常的 ; 通常發生在物件、陣列或函式呼叫時引數列表內部包含 ;,行號也指向了正確的位置。

Uncaught SyntaxError: Unexpected token ILLEGAL

同類錯誤:

  • Unterminated String Literal
  • Invalid Line Terminator

字串字面量缺少閉合的引號。

如何修復:確保所有字串都包含閉合的引號。

Uncaught TypeError: Cannot read property ‘foo’ of null, Uncaught TypeError: Cannot read property ‘foo’ of undefined

同類錯誤:

  • TypeError: someVal is null
  • Unable to get property ‘foo’ of undefined or null reference

嘗試將 null 過 undefined 作為一個物件使用,例如:

如何修復:通常是由於書寫失誤導致,確保錯誤提示的行號附近的變數都是書寫正確的。

Uncaught TypeError: Cannot set property ‘foo’ of null, Uncaught TypeError: Cannot set property ‘foo’ of undefined

同類錯誤:

  • TypeError: someVal is undefined
  • Unable to set property ‘foo’ of undefined or null reference

嘗試為值為 null 或 undefined 的物件的屬性賦值。

如何修復:這也通常是由於書寫錯誤導致,檢查錯誤提示的行號附近的變數名是否正確。

Uncaught RangeError: Maximum call stack size exceeded

同類錯誤:

  • Uncaught exception: RangeError: Maximum recursion depth exceeded
  • too much recursion
  • Stack overflow

通常是由程式邏輯問題,導致了無限遞迴的函式呼叫。

如何修復:檢查函式的遞迴呼叫,確保函式不是無限遞迴的。

Uncaught URIError: URI malformed

同類錯誤:URIError: malformed URI sequence

無效的 decodeURIComponent 呼叫將導致該錯誤。

如何修復:確保行號所指位置的 decodeURIComponent 呼叫的引數正確。

XMLHttpRequest cannot load http://some/url/. No ‘Access-Control-Allow-Origin’ header is present on the requested resource

同類錯誤:Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at http://some/url/

該錯誤總是由使用 XMLHttpRequest 時導致。

如何修復:確保請求的 url 滿足同源策略

InvalidStateError: An attempt was made to use an object that is not, or is no longer, usable

同類錯誤:

  • InvalidStateError
  • DOMException code 11

該錯誤表示呼叫物件的方法時,物件的狀態不對。在使用 XMLHttpRequest 時,在其準備好之前嘗試呼叫其中的方法將導致該錯誤。

上例中將導致錯誤,因為 setRequestHeader 方法只能在 xhr.open 之後呼叫。

如何修復:檢查行號指示的位置,確保程式碼執行在合適的時間,或在這之前新增必要的函式呼叫(比如xhr.open)。

相關文章