歡迎光臨
每天分享高質量文章

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

作者:bubkoo的部落格

網址:http://bubkoo.com/2015/01/25/Strange-JavaScript-Errors-and-How-to-Fix-Them/

點選“閱讀原文”可檢視本文網頁版

除錯 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)當作函式使用,但該值並不是一個函式。例如:

var foo = undefined;

foo();

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

var x = document.getElementByID(‘foo’);

訪問物件中不存在的屬性時將傳回 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’

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

if(doSomething() = ‘somevalue’)

在上面例子中,開發人員不小心將 == 寫成了 =,錯誤訊息“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 序列化一個存在迴圈取用的物件時。

var a = { };

var b = { a: a };

a.b = b;

JSON.stringify(a);

由於上面 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 作為一個物件使用,例如:

var someVal = null;

console.log(someVal.foo);

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

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 的物件的屬性賦值。

var someVal = null;

someVal.foo = 1;

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

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’ essay-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 時,在其準備好之前嘗試呼叫其中的方法將導致該錯誤。

var xhr = new XMLHttpRequest();

xhr.setRequestHeader(‘Some-Header’, ‘val’);

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

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

贊(0)

分享創造快樂