自定义错误有关问题

自定义异常问题

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 ...)似乎也存在以上问题.