2017-04-17 19:55 by 阿诚de窝, 29 阅读, 0 评论, ,
错误相关的调试和处理在开发中是特别重要的一种技能。
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代码执行停止了。