標籤:targe 來源 new 順序 mat res tps cat 沒有
在程式開發中難免會遇到一些錯誤,在成千上萬的代碼中去尋找錯誤很明顯相當於大海撈針,為此,每種電腦程式設計語言都要它獨特的一套錯誤處理與調試機制。當然,JavaScript也不例外。但是,接觸過javascript的人都知道,在調試js的過程中有時候真想砸電腦。因為在調試的過程中,控制台給出的錯誤非常難以理解,其次給出的行號不總有協助。雖然很多時候都要靠經驗去判斷,但是控制台給出的錯誤提示也並不是一點用都沒有。因為它會給你提供一些資訊協助你去判斷和尋找錯誤的來源。那這些有用的資訊是什嗎?前面已經說了,每種電腦程式設計語言都要它獨特的一套錯誤處理與調試機制,每種錯誤都有對應的錯誤類型,而當錯誤發生時,就會拋出相應類型的錯誤對象。JavaScript同樣如此,ECMA-262 定義了下列 7 種錯誤類型:
- Error 錯誤
- EvalError 全域錯誤
- RangeError 引用錯誤
- ReferenceError 參數錯誤
- SyntaxError 語法錯誤
- TypeError 類型錯誤
- URIError 編碼錯誤
其中, Error 是基底類型,其他錯誤類型都繼承自該類型。因此,所有錯誤類型共用了一組相同的屬性(錯誤對象中的方法全是預設的對象方法) 。 Error 類型的錯誤很少見,如果有也是瀏覽器拋出的,這個基底類型的主要目的是供開發人員拋出自訂錯誤。
EvalError 類型的錯誤會在使用 eval() 函數而發生異常時被拋出。ECMA-262 中對這個錯誤有如下描述: “如果以非直接調用的方式使用 eval 屬性的值(換句話說,沒有明確地將其名稱作為一個Identifier ,即用作 CallExpression 中的 MemberExpression ) ,或者為 eval 屬性賦值。 ”簡單地說,如果沒有把 eval() 當成函數調用,就會拋出錯誤,例如:
new eval(); //拋出 EvalErroreval = foo; //拋出 EvalError
在實踐中,瀏覽器不一定會在應該拋出錯誤時就拋出 EvalError 。例如,Firefox 4+和 IE8 對第一種情況會拋出 TypeError ,而第二種情況會成功執行,不發生錯誤。有鑒於此,加上在實際開發中極少會這樣使用 eval() ,所以遇到這種錯誤類型的可能性極小。其他類型錯誤在接下來會詳細說明。
錯誤類型:
TypeError
(類型錯誤)
對象用來表示值的類型非預期類型時發生的錯誤
錯誤原因:
當傳入函數的運算元或參數的類型並非操作符或函數所預期的類型時,將拋出一個 TypeError 類型錯誤。
(一)
錯誤資訊:
TypeError: undefined
is not a function (Firefox)
Uncaught TypeError: undefined is not a function (Chrome)
錯誤分析:
Uncaught TypeError:
這部分資訊通常不是很有用。Uncaught
表示錯誤沒有被 catch
語句捕獲,TypeError
是錯誤的名字。
undefined is not a function:
這部分資訊,你必須逐字閱讀。比如這裡表示代碼嘗試使用 undefined
,把它當做一個函數。
錯誤執行個體:
/** 當嘗試調用一個像方法的值時,這個值並不是一個方法*/var foo = undefined;foo(); //Uncaught TypeError: foo is not a function/** 當嘗試調用一個對象的方法時,輸錯了名字,也會觸發這個錯誤提示*/var x = document.getElementByID(‘foo‘); //Uncaught TypeError: document.getElementByID is not a function
(二)
錯誤資訊:
TypeError: foo is not a function (Firefox)
Uncaught TypeError: Cannot read property ‘foo‘ of null (Chrome)
錯誤分析:
Uncaught TypeError:
這部分資訊通常不是很有用。Uncaught
表示錯誤沒有被 catch
語句捕獲,TypeError
是錯誤的名字。
undefined is not a function:
這部分資訊,你必須逐字閱讀。比如這裡表示代碼嘗試使用 undefined
,把它當做一個函數。
錯誤執行個體:
/** 嘗試讀取 null
或者 undefined
,把它當成了對象*/var someVal = null;console.log(someVal.foo);
錯誤類型:
ReferenceError(引用錯誤)
對象表明一個不存在的變數被引用。
錯誤原因:
當你嘗試引用一個未被定義的變數時,將會拋出一個 ReferenceError引用錯誤
。
錯誤資訊:
ReferenceError: invalid assignment left-hand side (Firefox)
Uncaught ReferenceError: Invalid left-hand side in assignment (Chrome)
錯誤執行個體:
/** 嘗試給不能賦值的東西賦值,引起錯誤
* “left-hand side in assignment” 提及了等號左手邊的部分,因為左手邊包含不能賦值的東西*/function doSomething(){};if(doSomething() = ‘somevalue‘){}
; /** 當嘗試調用一個對象的方法時,輸錯了名字,也會觸發這個錯誤提示*/var x = document.getElementByID(‘foo‘); //Uncaught TypeError: document.getElementByID is not a function
錯誤類型:
RangeError
錯誤資訊:
RangeError: invalid array length (Firefox)RangeError: Invalid array length (Chrome)RangeError: Invalid array buffer length (Chrome)
錯誤原因:
試圖傳遞一個number參數給一個範圍內不包含該number的函數時則會引發RangeError。當傳遞一個不合法的length值作為Array
構造器的參數建立數組,或者傳遞錯誤值到數值計算方法(Number.toExponential()
,Number.toFixed()
,Number.toPrecision()
),會出現RangeError。
錯誤執行個體:
/*
* Array 和 ArrayBuffer 的 length(長度) 屬性被定義為一個32位無符號整形(unsigned 32-bit integer)的值,所以它只能儲存 0 - 232-1 之間的數。
* 當建立一個長度為負數或者長度大於等於232 的 Array
或者 ArrayBuffer
時,或者當設定 Array.length
屬性為負數或者長度大於等於232 的時候就會觸發這個錯誤
*/
new Array(Math.pow(2, 40))new Array(-1)new ArrayBuffer(Math.pow(2, 32))new ArrayBuffer(-1)let a = [];a.length = a.length - 1; // 將 length 屬性的值設定為 -1let b = new Array(Math.pow(2, 32) - 1);b.length = b.length + 1; // 將 length 屬性的值設定為 2^32
錯誤類型:
SyntaxError
錯誤原因:
SyntaxError
對象代表嘗試解析文法上不合法的代碼的錯誤。當Javascript語言解析代碼時,Javascript引擎發現了不符合文法規範的tokens或token順序時拋出SyntaxError
。可能是丟失運算子或者逸出字元等。
錯誤執行個體
/*
* 因為沒有使用 ”+“ 操作符來連接字串,JavaScript 認為 log
函數的參數的值只是 “PI: ”,在這種情況下,它應該用一個右括弧作為結束。
*/console.log("PI: " Math.PI);
//Uncaught SyntaxError: missing ) after argument list
/*
* 一個字串字面量少了結尾的引號
*/
var a=‘sd; //Uncaught SyntaxError: Invalid or unexpected token
如何解決:
[ ]
{ }
( )
這幾個符號不配對常常導致出錯。檢查所有的圓括弧和方括弧是否配對。行號指出的不僅是問題字元。
Unexpected /
跟Regex有關。此時行號通常是正確的。
Unexpected ;
對象或者數組字面量裡面有個;通常引起這個錯誤,或者函數調用的參數列表裡有個分號。此時的行號通常也是正確的。
JavaScript 調試常見報錯以及原因