Custom exception type

前端 未结 13 1740
生来不讨喜
生来不讨喜 2020-11-28 17:40

Can I define custom types for user-defined exceptions in JavaScript? If so, how would I do it?

13条回答
  •  误落风尘
    2020-11-28 18:03

    In short:

    • If you are using ES6 without transpilers:

      class CustomError extends Error { /* ... */}
      

      See Extending Error in Javascript with ES6 syntax for what's the current best practice

    • If you are using Babel transpiler:

    Option 1: use babel-plugin-transform-builtin-extend

    Option 2: do it yourself (inspired from that same library)

        function CustomError(...args) {
          const instance = Reflect.construct(Error, args);
          Reflect.setPrototypeOf(instance, Reflect.getPrototypeOf(this));
          return instance;
        }
        CustomError.prototype = Object.create(Error.prototype, {
          constructor: {
            value: Error,
            enumerable: false,
            writable: true,
            configurable: true
          }
        });
        Reflect.setPrototypeOf(CustomError, Error);
    
    • If you are using pure ES5:

      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;
      }
      
    • Alternative: use Classtrophobic framework

    Explanation:

    Why extending the Error class using ES6 and Babel is a problem?

    Because an instance of CustomError is not anymore recognized as such.

    class CustomError extends Error {}
    console.log(new CustomError('test') instanceof Error);// true
    console.log(new CustomError('test') instanceof CustomError);// false
    

    In fact, from the official documentation of Babel, you cannot extend any built-in JavaScript classes such as Date, Array, DOM or Error.

    The issue is described here:

    • Native extends breaks HTMLELement, Array, and others
    • an object of The class which is extends by base type like Array,Number,Object,String or Error is not instanceof this class

    What about the other SO answers?

    All the given answers fix the instanceof issue but you lose the regular error console.log:

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

    Whereas using the method mentioned above, not only you fix the instanceof issue but you also keep the regular error console.log:

    console.log(new CustomError('test'));
    // output:
    // Error: test
    //     at CustomError (:2:32)
    //     at :1:5
    

提交回复
热议问题