標籤:event對象 listen 基類 function 範圍 one lis str 學習
錯誤相關的調試和處理在開發中是特別重要的一種技能。
try-catch
我們來看下面的情況:
1 // noneFunc 這個方法並不存在2 window.noneFunc();3 // js 報錯後終止運行這行代碼並不會執行到4 console.log("hello");
為了避免不繼續執行後續代碼的情況,可以對可能拋出錯誤的代碼使用try-catch命令包圍。
1 try {2 // noneFunc 這個方法並不存在3 window.noneFunc();4 } catch (error) {5 // 一旦報錯將會跳到這裡執行6 console.log(error.message); // window.noneFunc is not a function7 }8 // 執行不中斷,這句代碼會得到執行9 console.log("hello");
這裡要注意error對象有多個屬性,但是message屬性是所有瀏覽器都支援的屬性。
finally
在try-catch語句中,finally語句是可選語句,其作用是無論被try-catch包含的代碼是否出現錯誤,都一定會執行finally語句包含的代碼,如下:
1 try { 2 window.test(); 3 } catch (error) { 4 console.log(error.message); 5 } finally { 6 console.log("finally code"); 7 } 8 9 //window.test is not a function10 //finally code
我們再看一下下面的代碼:
1 function test1() { 2 try { 3 return 0; 4 } catch (error) { 5 return 1; 6 } finally { 7 return 2; 8 } 9 }10 11 console.log(test1()); // 212 13 function test2() {14 try {15 return 0;16 } catch (error) {17 return 1;18 }19 }20 21 console.log(test2()); // 022 23 function test3() {24 try {25 // test 方法並不存在26 test();27 return 0;28 } catch (error) {29 return 1;30 } finally {31 return 2;32 }33 }34 35 console.log(test3()); // 236 37 function test4() {38 try {39 // test 方法並不存在40 test();41 return 0;42 } catch (error) {43 return 1;44 }45 }46 47 console.log(test4()); // 1
從上面的例子來看,在try-catch中包含的return語句都沒有執行返回,只會執行finally裡的return語句,再看下面的例子:
1 function test() { 2 try { 3 return 0; 4 } catch (error) { 5 return 1; 6 } finally { 7 console.log("finally"); 8 } 9 }10 11 console.log(test()); // 0
如果finally中沒有包含return語句,則先執行finally中的語句之後,在返回try-catch語句中的值,我們再看下面的例子:
1 function test1() { 2 var i = 0; 3 try { 4 return ++i; 5 } catch (error) { 6 return -1; 7 } finally { 8 return i; 9 }10 }11 12 console.log(test1()); // 113 14 function test2() {15 var i = 0;16 try {17 return i++;18 } catch (error) {19 return -1;20 } finally {21 return i;22 }23 }24 25 console.log(test2()); // 1
我們發現儘管沒有執行try-catch中的return語句,但是try-catch中的return語句仍然是執行了的,可以理解為如果finally中存在return關鍵字,則try-catch中的return關鍵字都被移除。
還有一種情況,如下:
1 function test1() { 2 var i = 0; 3 try { 4 return 0; 5 } catch (error) { 6 return 1; 7 } finally { 8 if (i != 0) { 9 return 2;10 }11 }12 }13 14 console.log(test1()); // 015 16 function test2() {17 var i = 0;18 try {19 return 0;20 } catch (error) {21 return 1;22 } finally {23 if (i == 0) {24 return 2;25 }26 }27 }28 29 console.log(test2()); // 2
我們還發現,如果由於條件判斷等原因,導致finally中的return語句沒有執行到,還是會返回try-catch中的return語句。
錯誤處理
在JavaScript中,有7種內建的錯誤類型:
- Error:其它6個錯誤類型的基類,也提供給開發人員自己定義新的錯誤類型。
- EvalError:執行eval()方法時的報錯。
- RangeError:數值超出範圍是報錯,如:new Array(-20)或new Array(Number.MAX_VALUE)。
- ReferenceError:找不到對象時的報錯。
- SyntaxError:執行eval()方法語法錯誤時報錯。
- TypeError:類型錯誤時的報錯,如:new 10或"name" in true時。
- URIError:在調用encodeURI和decodeURI時出錯的報錯。
對瀏覽器來說,只要try-catch包含的代碼拋出錯誤,則瀏覽器認為該錯誤已經被處理了,我們需要自行處理該錯誤。
拋出錯誤
拋出錯誤使用throw關鍵字,對於拋出的錯誤類型則沒有規定,可以是任意類型,而瀏覽器對使用者拋出的錯誤處理也和內建的錯誤一致,如果沒有try-catch進行包含的話,瀏覽器會暫停JS的執行。
我們可以簡單的拋出一個錯誤類型或自訂類型:
1 throw {msg:"my error"};2 throw new Error("our error");
我們可以繼承Error類型,實現自己的錯誤類型:
1 function MyError(msg, code) { 2 this.message = msg; 3 this.code = code; 4 } 5 6 MyError.prototype = new Error(); 7 8 try { 9 throw new MyError("my error", 1001);10 } catch (error) {11 console.log(error.message + ", " + error.code); // my error, 100112 }
當然,建議對catch中的error對象使用instanceof關鍵字進行類型篩選再來有針對性的處理錯誤。
error事件
error事件僅支援DOM0級的監聽方法,即不能通過addEventListener和removeEventListener方法來註冊和移除,同時該方法也不會建立對應的event對象,而是將報錯資訊直接傳遞過來。
可以理解error事件為整個頁面的try-catch語句,如下:
1 window.onerror = function (message, url, line) { 2 console.log("message: " + message + ", url: " + url + ", line: " + line); 3 // 返回 true 則瀏覽器不會列印錯誤資訊到 console 控制台,返回 false 則瀏覽器會列印錯誤資訊 4 return true; 5 }; 6 7 test(); 8 9 // 無論如何報錯後的代碼都不會再執行了10 console.log("run this code!");
該事件可以用來在應用開發時收集瀏覽器中沒有被try-catch包圍的語句拋出的錯誤,但實際上在發布給使用者的程式中,是不應該存在這樣的錯誤,因為error事件一旦拋出就表示JS代碼執行停止了。
HTML5學習筆記(二十六):JavaScript的錯誤處理