错误处理(一)
try-catch语句
try{ //可能会导致错误的代码 }catch(error){ //在错误发生时怎么处理 }
如果try块中的任何代码发生了错误,就会立即退出代码执行过程,然后接着执行catch块。此时,catch块会接收到一个包含错误信息到对象。与其他语言中不同到是,
即使你不想使用这个错误对象,也要给他起个名字。
try{ window.someNonexistentFunction(); }catch(error){ console.log(error.message); }
finally
function testFinally(){ try{ return 2; }catch(error){ return 1; }finally{ return 0; } }
只要代码中包含finally子句,那么无论try还是catch语句块中的return语句都将被忽略。因此,在使用finally子句之前,一定要非常清楚你想让代码怎么样。
错误类型
ECMA-262定义了7种错误类型: Error, EvalError, RangeError, ReferenceError, SyntaxError, TypeError, URIError
1)、Error
Error是基类型,其他错误类型都继承自该类型,Error类型都错误很少见,如果有也是浏览器抛出的;这个基类型的主要目的是提供开发人员抛出自定义错误
2)、EvalError
new eval(); //TypeError: eval is not a constructor
EvalError不再会被JavaScript抛出,但是EvalError对象仍然保持兼容性.有鉴于此,加上实际开发中很少使用eval(),所以遇到这种错误类型的可能性极小。
3)、RangeError
var items1 = new Array(-20); // RangeError: Invalid array length var items2 = new Array(Number.MAX_VALUE); //RangeError: Invalid array length
RangeError类型的错误会在数值超出相应范围触发。例如,在定义数组是,指定了数组不支持的项数
4)、ReferenceError
var obj = x; //ReferenceError: x is not defined eval = foo; // ReferenceError: foo is not defined
在找不到对象的情况下,会发生ReferenceError,通常,在访问不存在的变量时,就会发生这种错误
5)、SyntaxError
eval('a ++ b'); //SyntaxError: Unexpected identifier
当我们把语法错误的js字符传入eval()函数时,就会导致此类错误。如果语法错误的代码出现在eval()函数之外,则不太可能使用SyntaxError。
6)、TypeError
var o = new 10; //TypeError: 10 is not a constructor console.log('name' is true); //TypeError: Cannot use 'in' operator to search for 'name' in true Function.prototype.toString.call('name'); //TypeError: Function.prototype.toString requires that 'this' be a Function
TypeError类型在js中会经常用到,在变量中保存着意外的类型,或者访问不存在的方法时,都会导致这种错误,错误的原因多种多样,但归根结底还是由于在执行
特定类型的操作时,变量的类型并不符合要求所致。
7)、URIError
在使用encodeURI()或decodeURI(),而URI格式不正确时,就是导致URIError错误。这种错误也很少见,因为前面说的这个两个函数的容错性非常高。
8)、要想知道错误的类型,可以像下面这样处理
try{ someFunction() }catch(error){ if(error instanceof TypeError){ console.log('处理类型错误'); }else if(error instanceof ReferenceError){ console.log('处理引用错误'); }else{ console.log('处理其他类型的错误'); } }
9)、合理使用try-catch
使用try-catch最适合处理那些我们无法控制的错误。假设你在使用大型js库中的函数,该函数可能会有意无意地抛出一些错误。由于我们不能修改这个库的源代码,所以大可
将该函数的调用放在try-catch语句当中,万一有什么错误时,也好恰当地处理
在明明白白地知道自己地代码会发生错误,再使用try-catch语句就不太合适了。例如,如果传递给函数地参数时字符串而非树枝,就会造成函数出错,那么就应该检查参数地类型,
然后再决定如何去做。
抛出错误
在遇到throw操作符时,代码会立即停止执行。仅当有try-catch语句捕获被抛出的值时,代码才会继续执行
function process(values){ values.sort(); for(var i=0; i<values.length; i<len; i++){ if(values[i] > 100){ return values[i]; } } return -1; }
如果执行这个函数时传给它一个字符串参数,那么对sort()对调用就会失败。对此,不同对浏览器会给出不同对错误消息,但都不是特别明确。这个情况下,带有适当的
自定义错误能够显著提升代码的可维护性。
function process(values){ if(!(values instanceof Array)){ throw new Error("process(): Argument must be an array"); } values.sort(); for(var i=0; i<values.length; i<len; i++){ if(values[i] > 100){ return values[i]; } } return -1; }
建议读者在开发javascript代码的过程中,重点关注函数和可能导致函数执行失败的因素。良好的错误处理机制应该可以确保代码中只发生你自己抛出的错误。
error事件
任何没有通过try-catch处理的错误都会触发window对象的error事件。这个事件时web浏览器最早支持的事件之一。
window.onerror = function(message, url, line){ console.log(message); }
只要发生错误,无论是不是浏览器生成的,都会触发error事件,并执行这个事件处理程序。