javascript效仿java提供了异常机制,鼓励用异常来代替c时代的返回值判断,虽然javascript的throw语句可以后跟任何类型的表达式,但是规范情况下最好还是抛出Error以及Error子类的实例,自定义异常在javascript中利用原型链来模拟继承Error实现。
java的自定义异常类:
class CustomException extends Exception {
CustomException(String msg) {
super(msg);
}
}
那么理论上对应javascript的实现:
function CustomException() { Error.apply(this,arguments); } function t(){} t.prototype=Error.prototype; CustomException.prototype=new t(); CustomException.prototype.name="CustomException"; CustomException.prototype.constructor=CustomException;
但是如果使用的话:
try{ throw new CustomException("test"); } catch(e){ if(e instanceof CustomException) { alert(e.message); } }
会发现 message 属性并没有被设置到自定义异常实例上去,和java不同即Error构造器没有对当前实例进行初始化操作,参考 ecma规范:
When Error is called as a function rather than as a constructor, it creates and initialises a new Error object.
推测 Error 实现可能如下:
//返回native实例
function Error(msg){
//不等价 instanceof ,没有对应 js 操作
if(this 完全是 Error 实例 ) {
this.message=msg;
}
else
return new Error(msg)
}
Error.prototype=....
故和一般的继承模拟不一样:
function CustomException() { var e=Error.apply(this,arguments); //不等,this 对于 native Error函数不管用 console.log(e==this); } new CustomException("xx");
e !== this,所以这里 Error构造器的调用在自定义异常中就变的毫无意义,只能自己手动设置 message :
function CustomException(msg) { //无意义 //Error.apply(this,arguments); this.message=msg; }
PS1:native Error 实例在各个浏览期间差异比较大,可执行console.dir(new Error("x"));测试,但是标准只有message和name两个属性。
PS2:对于其它内置类型(Array,Date ...)似乎也存在以上问题.