try-catch
語句該語句最適合處理那些咱們沒法控制的錯誤,在明明白白地知道本身的代碼會發生錯誤時,再使用該語句就不太合適了。數據庫
ECMA-262第3版引入了try-catch語句,基本的語法以下所示:後端
try { // statements } catch(e) { // statements console.log(e); }
即便不使用這個錯誤對象,也要起個名字,對象中包含的實際信息因瀏覽器而異,但共同的是一個保存錯誤消息的跨域
message
屬性,ECMA-262還規定了一個保存錯誤類型的數組
name
屬性瀏覽器
全部瀏覽器都支持這個屬性(Opera 9以前的版本除外)。服務器
try { document.getElementByIfd("fdsa"); } catch(e) { // statements console.log(e.message); //document.getElementByIfd is not a function console.log(e.name); //TypeError }
又如:函數
try { var x = 1; var y = 0; console.log(z); } catch(e) { // statements console.log(e.message); //z is not defined console.log(e.name); //ReferenceError }
finally
子句雖然在try-catch塊中是可選的,但finally子句一經用,不管如何都會執行,甚至return語句都不會阻止,例如:this
function test() { try { return 1; } catch (error) { return 2; } finally { return 3; } }
上述代碼返回3,當try中代碼正常執行,finally會執行;當try中代碼出現錯誤,catch代碼會執行,finally代碼也會執行。編碼
每種錯誤都有對應的錯誤類型,而當錯誤發生時,就會拋出相應類型的錯誤對象,ECMA-262定義了7種錯誤類型:url
* `Error`: 基類型。 * `EvalError`: 使用eval()函數發生異常時拋出。 * `RangeError`: 數值超出相應範圍時拋出。 * `ReferenceError`: 找不到對象時拋出。 * `SyntaxError`: 使用eval()函數中的字符串有語法錯誤時拋出。 * `TypeError`: 在變量中保存意外類型或訪問不存在的方法時拋出。 * `URIError`: 使用encodeURI或decodeURI()中URI格式不正確時拋出。
與try-catch相配的還有一個
throw
操做符,用於拋出自定義錯誤。
拋出錯誤時,必須給throw操做符指定一個值,這個值的類型沒有要求,例如:
throw 123; throw "Hello World!";
在遇到throw操做符時,代碼會當即中止執行。
經過使用某種內置錯誤類型,能夠更真實
如:
try { throw new Error("nooo"); } catch (e) { console.log(e.message); //nooo console.log(e.name); //Error }
或:
throw new SyntaxError("wwwwtttttfffff");
也能夠建立自定義錯誤類型:
function CustomError (message) { this.name = "CustomError"; this.message = message; } CustomError.prototype = new Error(); var somebug = new CustomError("wtf"); try { throw somebug } catch(e) { console.log(e.name); //CustomError console.log(e.message); //wtf }
捕獲錯誤的目的在於避免瀏覽器以默認方式處理它們;而拋出錯誤的目的在於提供錯誤發生具體緣由的消息。
沒有經過try-catch處理的錯誤都會觸發window對象的
error
事件。任何瀏覽器中,onerror事件處理程序都不會建立event對象,但它能夠接受3個參數:錯誤消息、錯誤所在的URL和行號。
只要發生錯誤,不管是否是瀏覽器生成的,都會觸發error事件,並執行這個事件處理程序,若是在事件處理程序中返回false,能夠阻止瀏覽器報告錯誤的默認行爲,例如:
throw new Error("hello there"); window.onerror = function() { console.log(message); //Uncaught Error: hello there return false; }
圖像也支持error事件,只要圖像的src屬性中的URL不能返回能夠被識別的圖像格式,就會觸發error事件。
var x = new Image(); x.onerror = function () { console.log("message"); //message }; x.src = "fds.png";
常見的三種錯誤類型爲:
類型轉換錯誤
數據類型錯誤
通訊錯誤
類型轉換錯誤常發生在使用某個操做符或者自動轉換數據類型的場景
第一種常見錯誤是使用相等和不等操做符
console.log(1 == "1"); //true console.log(1 == true); //true
改進: 推薦使用全等( === ) 和非全等( !== ) 操做符, 來避免發生由於使用相等和不等操做符時引起的類型轉換錯誤;
console.log(1 === "1"); //false console.log(1 === true); //false
第二種常見錯誤是在流控制語句中使用非布爾值.
function concat(str1, str2) { if (str2) { return str1 + str2; } else { return str1; } } concat('a', 0); //a" concat('a', 1); //"a1"
該方法的目的是當第二個參數存在的時候返回兩個字符串拼接結果;
當第二個參數不存在的時候直接返回第一個參數.但是除了undefined會轉換爲布爾值false外, 0 也會轉換爲false, 而1則轉換爲true.所以調用結果與本意不太一致.
改進:
function concat(str1, str2) { if (typeof str2 == "string") { return str1 + str2; } else { return str1; } } concat('a', 0); //a" concat('a', 1); //"a"
在JavaScript中, 使用變量和函數參數以前是不會自動進行類型檢驗的.所以須要開發人員本身編寫數據類型檢測的代碼.例如:
function reverseSort(values) { if (values) { //這裏的判斷不能保證是數組類型 values.sort(); values.reverse(); } console.log(values); } reverseSort("a"); //TypeError
這裏若是傳入的參數不是數組類型, 就會發生數據類型錯誤.通常來講, 對於基本類型使用typeof進行類型檢驗, 對於對象類型使用instanceof進行類型檢驗.
function reverseSort(values) { if (values instanceof Array) { values.sort(); values.reverse(); } console.log(values); } reverseSort("a"); //a" reverseSort([6, 2, 3, 8, 1, 5]); //[8, 6, 5, 3, 2, 1]
場景一是在將數據發送給服務器以前, 未使用encodeURIComponent() 對數據進行編碼.例如:
www.cnblogs.com ? backurl = http : //www.cnblogs.com?a=1
解決方法是使用encodeURIComponent() 對backurl後面的參數進行編碼, 結果爲:
www.cnblogs.com ? backurl = http % 3 A % 2 F % 2 Fwww.cnblogs.com % 3 Fa % 3 D1
場景二是對於查詢字符串, 也要對於查詢參數的名和值都進行編碼.
若是把先後端的錯誤信息集中進行彙總記錄, 能極大的方便對數據庫錯誤日誌的分析.要把JavaScrpt錯誤記錄到服務器須要藉助image控件進行, 由於全部瀏覽器都支持image對象, 並且能夠避免跨域限制.
首先新建一個服務端頁面用於處理錯誤數據.這個頁面從查詢字符串中獲取錯誤數據, 而後將數據寫入到錯誤日誌中, 例如該頁面爲a.ashx.
而後在調用頁面中, 建立image對象, 而且爲其src屬性賦值, 這樣就能夠將錯誤信息發送到服務端頁面了.
function logError(msg) { var img = new Image(); img.src = 'a.ashx?msg=' + encodeURIComponent(msg); }