• 首页
  • vue
  • TypeScript
  • JavaScript
  • scss
  • css3
  • html5
  • php
  • MySQL
  • redis
  • jQuery
  • Error

    当运行时错误产生时,Error对象会被抛出。Error对象也可用于用户自定义的异常的基础对象。下面列出了各种内建的标准错误类型。


    描述

    当代码运行时的发生错误,会创建新的Error对象,并将其抛出。


    错误类型

    除了通用的Error构造函数外,JavaScript 还有其它类型的错误构造函数。对于客户端异常,详见异常处理语句。

    EvalError

    创建一个 error 实例,表示错误的原因:与eval()有关。

    RangeError

    创建一个 error 实例,表示错误的原因:数值变量或参数超出其有效范围。

    ReferenceError

    创建一个 error 实例,表示错误的原因:无效引用。

    SyntaxError

    创建一个 error 实例,表示错误的原因:语法错误。

    TypeError

    创建一个 error 实例,表示错误的原因:变量或参数不属于有效类型。

    URIError

    创建一个 error 实例,表示错误的原因:给encodeURI()decodeURI()传递的参数无效。

    AggregateError

    创建一个 error 实例,其中包裹了由一个操作产生且需要报告的多个错误。如:Promise.any()产生的错误。

    InternalError非标准

    创建一个代表 Javascript 引擎内部错误的异常抛出的实例。如:递归太多。


    构造函数

    Error()(en-US)

    创建一个新的Error对象。


    静态方法

    Error.captureStackTrace()非标准

    一个非标准的 V8 函数,用于在 Error 实例上创建stack属性。

    Error.stackTraceLimit非标准

    一个非标准的 V8 数值属性,用于限制错误堆栈跟踪中包含堆栈帧数量。

    Error.prepareStackTrace()非标准可选

    一个非标准的 V8 函数,如果提供了这一函数,V8 JavaScript 引擎会调用该函数来抛出异常。这个函数允许用户提供自定义的堆栈跟踪格式。


    实例属性

    Error.prototype.message

    错误消息。对于用户创建的Error对象,这是构造函数的第一个参数提供的字符串。

    Error.prototype.name

    错误名称。这是由构造函数决定的。

    Error.prototype.cause(en-US)

    表示导致当前错误被抛出的原因——通常是另一个错误。对于用户创建的Error对象,这是构造函数的第二个参数提供的值。

    Error.prototype.fileName非标准

    一个非标准的 Mozilla 属性,用于表示引发此错误的文件的路径。

    Error.prototype.lineNumber非标准

    一个非标准的 Mozilla 属性,用于表示引发此错误的代码所在的文件的行号。

    Error.prototype.columnNumber非标准

    一个非标准的 Mozilla 属性,用于表示引发此错误的代码在文件中所在行的列号。

    Error.prototype.stack非标准

    一个非标准的属性,用于堆栈跟踪。


    实例方法

    Error.prototype.toString()

    返回表示该对象的字符串。覆盖了Object.prototype.toString()方法。

    示例

    通常你会使用throw关键字来抛出你创建的Error对象。可以使用try...catch结构来处理异常:

    try {
      throw new Error('Whoops!')
    } catch (e) {
      console.error(e.name + ': ' + e.message)
    }
    


    处理一个特定错误

    你可以通过判断异常的类型来特定处理某一类的异常,即判断constructor属性,当使用现代 JavaScript 引擎时,可使用instanceof关键字:

    try {
      foo.bar()
    } catch (e) {
      if (e instanceof EvalError) {
        console.error(e.name + ': ' + e.message)
      } else if (e instanceof RangeError) {
        console.error(e.name + ': ' + e.message)
      }
      // ... etc
    
      else {
        // If none of our cases matched leave the Error unhandled
        throw e;
      }
    }
    


    区分相似的错误

    有时,对于代码块的错误需要根据其原因进行不同的处理,但错误的原因又较为相似(例如:错误的类型和消息均相同)。

    如果你无法控制原有错误的抛出,那么一种方法是捕获错误然后抛出一个新的错误,并在新的错误中给出更加具体的错误消息。原始错误应该被传递到新的Error的构造函数的option参数(cause属性)中,这确保了原始的错误和堆栈追踪信息在上层的 try/catch 块中可用。

    以下示例展示了两种方法会在失败时抛出相似的错误(doFailSomeWay()doFailAnotherWay()):

    function doWork() {
      try {
        doFailSomeWay();
      } catch (err) {
        throw new Error('Failed in some way', { cause: err });
      }
      try {
        doFailAnotherWay();
      } catch (err) {
        throw new Error('Failed in another way', { cause: err });
      }
    }
    
    try {
      doWork();
    } catch (err) {
      switch(err.message) {
        case 'Failed in some way':
          handleFailSomeWay(err.cause);
          break;
        case 'Failed in another way':
          handleFailAnotherWay(err.cause);
          break;
      }
    }
    

    备注:如果你在创建一个函数库,你应该使用错误原因来区分不同的错误——而不是要求你的函数库的使用者来解析错误消息。相关的示例,请参见提供错误原因(en-US)

    自定义错误类型也可以使用cause属性,前提是通过super()调用子类的构造函数时传递options参数。

    class MyError extends Error {
      constructor(/* some arguments */) {
        // Needs to pass both `message` and `options` to install the "cause" property.
        super(message, options);
      }
    }
    


    自定义错误类型

    你可能希望自定义基于Error的异常类型,使得你能够throw new MyError()并可以使用instanceof MyError来检查某个异常的类型。这种需求的通用解决方法如下。

    参考 StackOverflow 上关于“What's a good way to extend Error in JavaScript?”的讨论。

    ES6 自定义错误类

    警告: Babel 7 之前的版本可以处理CustomError类方法,但类方法需要使用 Object.defineProperty()定义。否则,旧版本的 Babel 和其它转译器在没有额外配置的情况下将无法正确处理下面的代码。

    备注:在使用 ES2015 的类时,一些浏览器会在堆栈跟踪中包含CustomError构造函数。

    class CustomError extends Error {
      constructor(foo = 'bar', ...params) {
        // Pass remaining arguments (including vendor specific ones) to parent constructor
        super(...params);
    
        // Maintains proper stack trace for where our error was thrown (only available on V8)
        if (Error.captureStackTrace) {
          Error.captureStackTrace(this, CustomError);
        }
    
        this.name = 'CustomError';
        // Custom debugging information
        this.foo = foo;
        this.date = new Date();
      }
    }
    
    try {
      throw new CustomError('baz', 'bazMessage');
    } catch(e) {
      console.error(e.name);    // CustomError
      console.error(e.foo);     // baz
      console.error(e.message); // bazMessage
      console.error(e.stack);   // stacktrace
    }
    

    ES5 自定义错误对象

    警告:在使用原型声明时,所有浏览器都会在堆栈跟踪中包含CustomError的构造函数。

    function CustomError(foo, message, fileName, lineNumber) {
      var instance = new Error(message, fileName, lineNumber);
      instance.foo = foo;
      Object.setPrototypeOf(instance, CustomError.prototype);
      if (Error.captureStackTrace) {
        Error.captureStackTrace(instance, CustomError);
      }
      return instance;
    }
    
    Object.setPrototypeOf(CustomError.prototype, Error.prototype);
    
    Object.setPrototypeOf(CustomError, Error);
    
    CustomError.prototype.name = 'CustomError';
    
    try {
      throw new CustomError('baz', 'bazMessage');
    } catch(e) {
      console.error(e.name); // CustomError
      console.error(e.foo); // baz
      console.error(e.message); // bazMessage
    }
    

    下篇:new Error()