Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/442.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 自定义异常类型_Javascript_Exception - Fatal编程技术网

Javascript 自定义异常类型

Javascript 自定义异常类型,javascript,exception,Javascript,Exception,我可以在JavaScript中为用户定义的异常定义自定义类型吗?如果是这样的话,我该怎么做呢?使用该语句 JavaScript不关心异常类型是什么(就像Java一样)。 JavaScript只是注意到,有一个异常,当您捕捉到它时,您可以“查看”异常所说的内容 如果必须抛出不同的异常类型,我建议使用包含异常字符串/对象(即消息)的变量。在需要的地方使用“throw myException”,并在catch中,将捕获的异常与myException进行比较。是。你可以抛出你想要的任何东西:整数,字符串

我可以在JavaScript中为用户定义的异常定义自定义类型吗?如果是这样的话,我该怎么做呢?

使用该语句

JavaScript不关心异常类型是什么(就像Java一样)。 JavaScript只是注意到,有一个异常,当您捕捉到它时,您可以“查看”异常所说的内容


如果必须抛出不同的异常类型,我建议使用包含异常字符串/对象(即消息)的变量。在需要的地方使用“throw myException”,并在catch中,将捕获的异常与myException进行比较。

是。你可以抛出你想要的任何东西:整数,字符串,对象,等等。如果您想抛出一个对象,那么只需创建一个新对象,就像您在其他情况下创建一个对象一样,然后抛出它。有几个示例。

您可以实现自己的异常及其处理,例如:

//定义异常“类”
函数NotNumberException(){}
函数NotPositionEnumberException(){}
//尝试一些代码
试一试{
//某些函数/代码可能会引发
如果(isNaN(值))
抛出新的NotNumberException();
其他的
如果(值<0)
抛出新的NotPositionEnumberException();
}
捕获(e){
如果(例如NotNumberException的实例){
警报(“不是数字”);
}
其他的
if(NotPositionEnumberException的实例){
警报(“非正数”);
}
}
还有另一种用于捕获类型化异常的语法,尽管这在每个浏览器中都不起作用(例如,在IE中不起作用):

//定义异常“类”
函数NotNumberException(){}
函数NotPositionEnumberException(){}
//尝试一些代码
试一试{
//某些函数/代码可能会引发
如果(isNaN(值))
抛出新的NotNumberException();
其他的
如果(值<0)
抛出新的NotPositionEnumberException();
}
捕获(如果NotNumberException的实例为e,则为e){
警报(“不是数字”);
}
捕获(如果e实例为NotPositionEnumberException){
警报(“非正数”);
}
来自:

抛出{
名称:“系统错误”,
关卡:“显示停止符”,
消息:“检测到错误。请与系统管理员联系。”,
htmlMessage:“检测到错误。请与管理员联系。”,
toString:function(){返回this.name+:“+this.message;}
}; 
这允许使用类似

try {
  something();
 } catch(e) {
  if(e instanceof MyError)
   doSomethingElse();
  else if(e instanceof Error)
   andNowForSomethingCompletelyDifferent();
}

下面是如何创建与本机
错误
行为完全相同的自定义错误。目前,这种技术只能在Chrome和node.js中使用。如果您不了解它的功能,我也不建议您使用它

Error.createCustromConstructor = (function() {

    function define(obj, prop, value) {
        Object.defineProperty(obj, prop, {
            value: value,
            configurable: true,
            enumerable: false,
            writable: true
        });
    }

    return function(name, init, proto) {
        var CustomError;
        proto = proto || {};
        function build(message) {
            var self = this instanceof CustomError
                ? this
                : Object.create(CustomError.prototype);
            Error.apply(self, arguments);
            Error.captureStackTrace(self, CustomError);
            if (message != undefined) {
                define(self, 'message', String(message));
            }
            define(self, 'arguments', undefined);
            define(self, 'type', undefined);
            if (typeof init == 'function') {
                init.apply(self, arguments);
            }
            return self;
        }
        eval('CustomError = function ' + name + '() {' +
            'return build.apply(this, arguments); }');
        CustomError.prototype = Object.create(Error.prototype);
        define(CustomError.prototype, 'constructor', CustomError);
        for (var key in proto) {
            define(CustomError.prototype, key, proto[key]);
        }
        Object.defineProperty(CustomError.prototype, 'name', { value: name });
        return CustomError;
    }

})();
结果我们得到了

/**
 * name   The name of the constructor name
 * init   User-defined initialization function
 * proto  It's enumerable members will be added to 
 *        prototype of created constructor
 **/
Error.createCustromConstructor = function(name, init, proto)
然后你可以这样使用它:

var NotImplementedError = Error.createCustromConstructor('NotImplementedError');
并使用
NotImplementedError
,就像使用
Error
一样:

throw new NotImplementedError();
var err = new NotImplementedError();
var err = NotImplementedError('Not yet...');
预计它将表现为:

err instanceof NotImplementedError               // -> true
err instanceof Error                             // -> true
NotImplementedError.prototype.isPrototypeOf(err) // -> true
Error.prototype.isPrototypeOf(err)               // -> true
err.constructor.name                             // -> NotImplementedError
err.name                                         // -> NotImplementedError
err.message                                      // -> Not yet...
err.toString()                                   // -> NotImplementedError: Not yet...
err.stack                                        // -> works fine!
err instanceof InvalidArgumentException          // -> true
err instanceof Error                             // -> true
InvalidArgumentException.prototype.isPrototypeOf(err) // -> true
Error.prototype.isPrototypeOf(err)               // -> true
err.constructor.name                             // -> InvalidArgumentException
err.name                                         // -> InvalidArgumentException
err.message                                      // -> Not yet...
err.toString()                                   // -> InvalidArgumentException: Not yet...
err.stack                                        // -> works fine!
请注意,
error.stack
工作绝对正确,不会包含
NotImplementedError
构造函数调用(多亏了v8的
error.captureStackTrace()


注意。存在丑陋的
eval()
。使用它的唯一原因是为了获得正确的
err.constructor.name
。如果您不需要它,您可以稍微简化一切。

我经常使用原型继承的方法。重写
toString()
的好处是,Firebug等工具将把实际信息而不是
[object object]
记录到控制台,以获取未捕获的异常

使用
instanceof
确定异常的类型

main.js Exception.js DuplicateIdeException.js
现在,我们将添加原因或任何我们想要的属性设置为error对象并检索它。通过使错误更合理。

您应该创建一个自定义异常,该异常通常继承自错误。例如:

function InvalidArgumentException(message) {
    this.message = message;
    // Use V8's native method if available, otherwise fallback
    if ("captureStackTrace" in Error)
        Error.captureStackTrace(this, InvalidArgumentException);
    else
        this.stack = (new Error()).stack;
}

InvalidArgumentException.prototype = Object.create(Error.prototype);
InvalidArgumentException.prototype.name = "InvalidArgumentException";
InvalidArgumentException.prototype.constructor = InvalidArgumentException;
这基本上是上面发布的一个简化版本,它增强了堆栈跟踪在Firefox和其他浏览器上的工作。它满足了他发布的相同测试:

用法:

throw new InvalidArgumentException();
var err = new InvalidArgumentException("Not yet...");
预计它将表现为:

err instanceof NotImplementedError               // -> true
err instanceof Error                             // -> true
NotImplementedError.prototype.isPrototypeOf(err) // -> true
Error.prototype.isPrototypeOf(err)               // -> true
err.constructor.name                             // -> NotImplementedError
err.name                                         // -> NotImplementedError
err.message                                      // -> Not yet...
err.toString()                                   // -> NotImplementedError: Not yet...
err.stack                                        // -> works fine!
err instanceof InvalidArgumentException          // -> true
err instanceof Error                             // -> true
InvalidArgumentException.prototype.isPrototypeOf(err) // -> true
Error.prototype.isPrototypeOf(err)               // -> true
err.constructor.name                             // -> InvalidArgumentException
err.name                                         // -> InvalidArgumentException
err.message                                      // -> Not yet...
err.toString()                                   // -> InvalidArgumentException: Not yet...
err.stack                                        // -> works fine!
请参见MDN中的

如果需要定义多个错误(测试代码!):


代码主要来自:

用于ES2015类的答案的替代方案

class InvalidArgumentException extends Error {
    constructor(message) {
        super();
        Error.captureStackTrace(this, this.constructor);
        this.name = "InvalidArgumentException";
        this.message = message;
    }
}

简而言之:

  • 如果您使用的是不带Transpiler的ES6

    class CustomError extends Error { /* ... */}
    
    function CustomError(message, fileName, lineNumber) {
      const instance = new Error(message, fileName, lineNumber);
      Object.setPrototypeOf(instance, Object.getPrototypeOf(this));
      return instance;
    }
    CustomError.prototype = Object.create(Error.prototype, {
      constructor: {
        value: Error,
        enumerable: false,
        writable: true,
        configurable: true
      }
    });
    if (Object.setPrototypeOf){
        Object.setPrototypeOf(CustomError, Error);
    } else {
        CustomError.__proto__ = Error;
    }
    
    查看当前的最佳实践是什么

  • 如果您使用的是巴贝尔transpiler

  • class CustomError extends Error { /* ... */}
    
    function CustomError(message, fileName, lineNumber) {
      const instance = new Error(message, fileName, lineNumber);
      Object.setPrototypeOf(instance, Object.getPrototypeOf(this));
      return instance;
    }
    CustomError.prototype = Object.create(Error.prototype, {
      constructor: {
        value: Error,
        enumerable: false,
        writable: true,
        configurable: true
      }
    });
    if (Object.setPrototypeOf){
        Object.setPrototypeOf(CustomError, Error);
    } else {
        CustomError.__proto__ = Error;
    }
    
备选案文1:使用

选项2:自己动手(灵感来自同一个库)

  • 如果您使用的是纯ES5:

    class CustomError extends Error { /* ... */}
    
    function CustomError(message, fileName, lineNumber) {
      const instance = new Error(message, fileName, lineNumber);
      Object.setPrototypeOf(instance, Object.getPrototypeOf(this));
      return instance;
    }
    CustomError.prototype = Object.create(Error.prototype, {
      constructor: {
        value: Error,
        enumerable: false,
        writable: true,
        configurable: true
      }
    });
    if (Object.setPrototypeOf){
        Object.setPrototypeOf(CustomError, Error);
    } else {
        CustomError.__proto__ = Error;
    }
    
  • 备选方案:使用框架

说明:

为什么使用ES6和Babel扩展错误类是一个问题

因为CustomError的实例不再被识别为这样的实例

class CustomError extends Error {}
console.log(new CustomError('test') instanceof Error);// true
console.log(new CustomError('test') instanceof CustomError);// false
事实上,从Babel的官方文档中,您可以看到诸如
Date
Array
DOM
Error

这里描述了这个问题:

其他答案呢

所有给出的答案都修复了
实例的问题,但您丢失了常规错误
控制台。日志

console.log(new CustomError('test'));
// output:
// CustomError {name: "MyError", message: "test", stack: "Error↵    at CustomError (<anonymous>:4:19)↵    at <anonymous>:1:5"}
console.log(new CustomError('test'));
// output:
// Error: test
//     at CustomError (<anonymous>:2:32)
//     at <anonymous>:1:5
ES6

有了新的类和扩展关键字,现在更容易了:

class CustomError extends Error {
  constructor(message) {
    super(message);
    //something
  }
}

@b、 《JavaScript:好的部分》(IMO好书)中有很长的篇幅。这个GoogleBooks预览显示了以下部分:添加一个toString方法将使它在javascript控制台中很好地显示出来。如果没有,则显示为:未捕获#如果使用toString,则显示为:未捕获系统错误:检测到错误。请与系统管理员联系。这将不允许您堆叠跟踪,除非您从error继承。您如何在catch块中进行筛选以仅处理此自定义错误?@overdrivr类似于⦃
catch(e){if(e instanceof TypeError){…}else{throw e;}}}
class CustomError extends Error {
  constructor(message) {
    super(message);
    //something
  }
}