JavaScript Object Oriented Programming – Exceptions

「例外(Exceptions)」是一个特别且重要的处理错误的方法。

 

Check-first error handling

假设我们要执行func这个method,首先会检查这个method是否存在。

 

if (window.func) {

func();

}

但检查了是否存在,不代表型别正确,因此我们必须再检查这个method的型别是否为function。

 

if (typeof(func) == ‘function’) {

func();

}

但意外或错误是永远检查不完的,例如,这个method的内部可能有些问题。因此,我们可以改用「Try..Catch」来处理。

 

The try..catch construct

上一个例子是预先把可能发生的问题都检查一次,例如:存在与否、型别是否正确,如果通过检查再执行。而「Try..Catch」从另外一个角度来处理- 先执行,如果有错再处理。范例如下。

 

try {

func();

}

catch(e) {

alert(e);

}

这个「e」会告诉我们到底发生什么问题。

 

try {

var a = 5, res = func(a);

 

if (res > 0) {

doA();

}

else {

doB();

}

}

catch(e) {

console.log(“name: ” + e.name); //name: ReferenceError

console.log(“message: ” + e.message); //message: doB is not defined

}

由错误讯息可知,doB这个function没有被定义,因此无法执行而出错。

 

The full form of try..catch..finally

try {

//try statemenets ..

}

catch(exception) {

//catch statements ..

}

finally {

//finally statements ..

}

首先执行try区块内的程序码,如果没有出错,则catch区块会被忽略不执行。如果有错误产生,则exception会被设定值,catch区块会被执行。无论如何,最后,finally区块都会被执行。

 

try..catch..finally and return

 

在try区块执行return statments,控制权会在执行完finally区块后才交回给原呼叫的function。所以如下程序码所示,会先alert 「done」,再alert 「2」。

 

function inc(a) {

try {

return a+1;

}

catch(e) {

//catch statements…

}

finally {

alert(‘done’); //1. alert “done”

}

}

alert( inc(1) ); //2. alert “2”

The throw statement

基本上,错误可以分为两种:「Programmatic errors」和「Execution flow errors」。

 

Programmatic errors:程序撰写错误,例如:错字。

Execution flow errors:执行时的错误,例如:使用者输入不符合预定格式的资料,程序提示格式有误并重新输入。

因此,使用try…catch与throw于Execution flow errors是一个不错的选择,范例如下。

 

try {

throw 5;

}

catch(e) {

alert(“Caught: ” + e);

}

A validator example

 

假设我们需要一个年龄的验证工具,帮助我们检查使用者输入的年龄是否合法。如果没有输入任何东西,则跳出;如果输入非文字,则丢出错误;如果是数字,则显示可接受的讯息。

 

function validatorAge(age){

if(age === ”){

return; //no age to valid

}

age = +age;

 

if(isNaN(age)){

throw {

name: ‘BadAge’,

message: ‘Age out of range’

}

}

}

 

try {

var age = prompt(‘Enter your age’);

validatorAge(age);

alert(‘The age is accepted’);

}

catch(e){

alert(‘Error: ‘ + e.message);

}

Changes in the usage pattern

 

除了try…catch的用法,当然我们也可以使用error-checking的方法。

 

function validatorAge(age){

if(age === ”){

return; //no age to valid

}

age = +age;

 

if(isNaN(age)){

return false;

}

else{

return true;

}

}

 

var value = prompt(‘Enter your age’),

error = validatorAge(value);

 

if(!error){

//process error

alert(‘Invalid error!’);

}

else{

//success

alert(‘The age is accepted’);

}

Comparison

 

try..catch较简洁,可读性较高。

error-checking无法检查所有的错误,但try..catch确可捕捉所有错误,所以try..catch是唯一万无一失的方法。尤其在检查浏览器兼容的错误的时候。

Exception analysis and rethrow

有时候,程序码可能会产生不同种类的错误。因此,我们使用「if」来选择适当的动作。结构类似如下:

 

try {

// 1. do smth

}

catch(e) {

if (e instanceof ValidationError) {

// 2.1 process e

}

else if (e instanceof PermissionError) {

// 2.2 process e

}

else {

// 3. we don’t know how to deal with e

throw e

}

}

在try区块可能丢出了某些错误,有些错误是我们已知的,例如:ValidationError和PermissionError,然后去处理这些已知的e。但有些我们并不确定,因此直接丢出e。这里丢出的e,需要由外层的try..catch来处理。

 

Summary

try..catch..finally将多种检查合并在一个try区块内执行,并将error-handlin分散在catch区块来做错误的处理。

try..catch..finally能捕捉和处理所有的错误。丢出的错误可使用JavaScript-generated或自行定义的。

错误建议继承基本错误对象。因此,可用instanceof来检查错误的类型,如上范例检查ValidationError和PermissionError。

点击这里给我发消息