try{ //通常来讲,这里的代码会从头到尾而不会产生任何问题 //但有时会抛出一个异常,要么是由throw语句直接抛出,要么通过调用一个方法间接抛出 }catch(e){ //当且仅当try语句块抛出了异常,才会执行这里的代码 //这里可以通过局部变量e来获得对Error对象或者抛出的其他值的引用 //这里的代码块可以基于某种原因处理这个异常,也可以忽略这个异常,还可以通过throw语句重新抛出异常 }finally{ //不管try语句是否抛出了异常,finally里的逻辑总是会执行,终止try语句块的方式有: //1、正常终止,执行完语句块的最后一条语句 //2、通过break、continue或return语句终止 //3、抛出一个异常,异常被catch从句捕获 //4、抛出一个异常,异常未被捕获,继续向上传播 }
一般地,把所有可能会抛出错误的代码都放在try语句块中,而把那些用于错误处理的代码放在catch块中
如果try块中的任何代码发生了错误,就会立即退出代码执行过程,然后接着执行catch块。此时,catch块会接收到一个错误信息的对象,这个对象中包含的实际信息会因浏览器而异,但共同的是有一个保存着错误消息的message属性
[注意]一定要给error对象起个名字,置空会报语法错误
try{ q; }catch(error){ alert(error.message);//q is not defined } //Uncaught SyntaxError: Unexpected token ) try{ q; }catch(){ alert(error.message); }
catch接受一个参数,表示try代码块抛出的值
function throwIt(exception) { try { throw exception; } catch (e) { console.log('Caught: '+ e); } } throwIt(3);// Caught: 3 throwIt('hello');// Caught: hello throwIt(new Error('An error happened'));// Caught: Error: An error happened
catch代码块捕获错误之后,程序不会中断,会按照正常流程继续执行下去
try{ throw "出错了"; } catch (e) { console.log(111); } console.log(222); // 111 // 222
为了捕捉不同类型的错误,catch代码块之中可以加入判断语句
try { foo.bar(); } catch (e) { if (e instanceof EvalError) { console.log(e.name + ": " + e.message); } else if (e instanceof RangeError) { console.log(e.name + ": " + e.message); } // ... }
虽然finally子句在try-catch语句中是可选的,但finally子句一经使用,其代码无论如何都会执行。换句话说,try语句块中的代码全部正常执行,finally子句会执行;如果因为出错而执行了catch语句块,finally子句照样还会执行。只要代码中包含finally子句,则无论try或catch语句块中包含什么代码——甚至return语句,都不会阻止finally子句的执行
//由于没有catch语句块,所以错误没有捕获。执行finally代码块以后,程序就中断在错误抛出的地方 function cleansUp() { try { throw new Error('出错了……'); console.log('此行不会执行'); } finally { console.log('完成清理工作'); } } cleansUp(); // 完成清理工作 // Error: 出错了……
function testFinnally(){ try{ return 2; }catch(error){ return 1; }finally{ return 0; } } testFinnally();//0
[注意]return语句的count的值,是在finally代码块运行之前,就获取完成了
var count = 0; function countUp() { try { return count; } finally { count++; } } countUp();// 0 console.log(count);// 1
function f() { try { console.log(0); throw "bug"; } catch(e) { console.log(1); return true; // 这句原本会延迟到finally代码块结束再执行 console.log(2); // 不会运行 } finally { console.log(3); return false; // 这句会覆盖掉前面那句return console.log(4); // 不会运行 } console.log(5); // 不会运行 } var result = f(); // 0 // 1 // 3 console.log(result);// false
【tips】块级作用域
try-catch语句的一个常见用途是创建块级作用域,其中声明的变量仅仅在catch内部有效
ES6引入了let关键字,为其声明的变量创建块级作用域。但是,在目前ES3和ES5的情况下,常常使用try-catch语句来实现类似的效果
由下面代码可知,e仅存在于catch分句内部,当试图从别处引用它时会抛出错误
try{ throw new Error();//抛出错误 }catch(e){ console.log(e);//Error(…) } console.log(e);//Uncaught ReferenceError: e is not defined
常见错误错误处理的核心是首先要知道代码里会发生什么错误。由于javaScript是松散类型的,而且也不会验证函数的参数,因此错误只会在代码期间出现。一般来说,需要关注三种错误:类型转换错误、数据类型错误、通信错误
【类型转换错误】
类型转换错误发生在使用某个操作符,或者使用其他可能自动转换值的数据类型的语言结构时