代码之家  ›  专栏  ›  技术社区  ›  cdleary

如何在JavaScript中创建自定义错误?

  •  280
  • cdleary  · 技术社区  · 16 年前

    出于某种原因,构造函数委托在以下代码段中似乎不起作用:

    function NotImplementedError() { 
      Error.apply(this, arguments); 
    }
    NotImplementedError.prototype = new Error();
    
    var nie = new NotImplementedError("some message");
    console.log("The message is: '"+nie.message+"'")
    

    运行此命令可以 The message is: '' 关于为什么,或者是否有更好的方法来创造一个新的 Error apply 向原住民致敬

    25 回复  |  直到 12 年前
        1
  •  183
  •   JLRishe    9 年前

    更新你的代码,将你的原型分配给Error.prototype,instanceof和asserts都可以工作。

    function NotImplementedError(message = "") {
        this.name = "NotImplementedError";
        this.message = message;
    }
    NotImplementedError.prototype = Error.prototype;
    

    但是,我只会抛出你自己的对象,并检查name属性。

    throw {name : "NotImplementedError", message : "too lazy to implement"}; 
    

    根据评论进行编辑

    在查看评论并试图记住我为什么要将原型分配给 Error.prototype 而不是 new Error() 就像尼古拉斯·扎卡斯在他的 article ,我创建了一个 jsFiddle 代码如下:

    function NotImplementedError(message = "") {
      this.name = "NotImplementedError";
      this.message = message;
    }
    NotImplementedError.prototype = Error.prototype;
    
    function NotImplementedError2(message = "") {
      this.message = message;
    }
    NotImplementedError2.prototype = new Error();
    
    try {
      var e = new NotImplementedError("NotImplementedError message");
      throw e;
    } catch (ex1) {
      console.log(ex1.stack);
      console.log("ex1 instanceof NotImplementedError = " + (ex1 instanceof NotImplementedError));
      console.log("ex1 instanceof Error = " + (ex1 instanceof Error));
      console.log("ex1.name = " + ex1.name);
      console.log("ex1.message = " + ex1.message);
    }
    
    try {
      var e = new NotImplementedError2("NotImplementedError2 message");
      throw e;
    } catch (ex1) {
      console.log(ex1.stack);
      console.log("ex1 instanceof NotImplementedError2 = " + (ex1 instanceof NotImplementedError2));
      console.log("ex1 instanceof Error = " + (ex1 instanceof Error));
      console.log("ex1.name = " + ex1.name);
      console.log("ex1.message = " + ex1.message);
    }

    控制台输出如下。

    undefined
    ex1 instanceof NotImplementedError = true
    ex1 instanceof Error = true
    ex1.name = NotImplementedError
    ex1.message = NotImplementedError message
    Error
        at window.onload (http://fiddle.jshell.net/MwMEJ/show/:29:34)
    ex1 instanceof NotImplementedError2 = true
    ex1 instanceof Error = true
    ex1.name = Error
    ex1.message = NotImplementedError2 message
    

    这证实了我遇到的“问题”是错误的堆栈属性是行号,其中 新错误() 是创建的,而不是在哪里 throw e 发生。然而,这可能比有副作用要好 NotImplementedError.prototype.name = "NotImplementedError" 影响Error对象的行。

    此外,请注意 NotImplementedError2 ,当我没有设置 .name 明确地说,它等于“错误”。然而,正如评论中提到的,因为该版本将原型设置为 新错误() ,我可以设置 NotImplementedError2.prototype.name = "NotImplementedError2"

        2
  •  85
  •   Community CDub    8 年前

    在ES2015中,您可以使用 class 要干净利落地做到这一点:

    class NotImplemented extends Error {
      constructor(message = "", ...args) {
        super(message, ...args);
        this.message = message + " has not yet been implemented.";
      }
    }
    

    这不会修改全局 Error 原型,允许您进行自定义 message , name ,以及其他属性,并正确捕获堆栈。它也很易读。

    当然,您可能需要使用以下工具 babel 如果您的代码将在较旧的浏览器上运行。

        3
  •  20
  •   ThomasReggi    10 年前

    以上所有的答案都非常糟糕——真的。即使是有107个上升点的那个!真正的答案在这里,伙计们:

    Inheriting from the Error object - where is the message property?

    太长,读不下去了

    A.原因 message 没有设置是吗 Error 是一个函数,它返回一个新的Error对象,并执行以下操作 操纵 this 无论如何。

    function MyError() {
        var temp = Error.apply(this, arguments);
        temp.name = this.name = 'MyError';
        this.message = temp.message;
        if(Object.defineProperty) {
            // getter for more optimizy goodness
            /*this.stack = */Object.defineProperty(this, 'stack', { 
                get: function() {
                    return temp.stack
                },
                configurable: true // so you can change it if you want
            })
        } else {
            this.stack = temp.stack
        }
    }
    //inherit prototype using ECMAScript 5 (IE 9+)
    MyError.prototype = Object.create(Error.prototype, {
        constructor: {
            value: MyError,
            writable: true,
            configurable: true
        }
    });
    
    var myError = new MyError("message");
    console.log("The message is: '" + myError.message + "'"); // The message is: 'message'
    console.log(myError instanceof Error); // true
    console.log(myError instanceof MyError); // true
    console.log(myError.toString()); // MyError: message
    console.log(myError.stack); // MyError: message \n 
    // <stack trace ...>
    
    
     
    //for EMCAScript 4 or ealier (IE 8 or ealier), inherit prototype this way instead of above code:
    /*
    var IntermediateInheritor = function() {};
    IntermediateInheritor.prototype = Error.prototype;
    MyError.prototype = new IntermediateInheritor();
    */

    tmp 设置它们而不是仅显式设置时出错 stack 消息 ,但该诡计在ie中不受支持<9

        4
  •  14
  •   rattray    8 年前

    如果有人想知道如何创建自定义错误 获取堆栈跟踪:

    function CustomError(message) {
      this.name = 'CustomError';
      this.message = message || '';
      var error = new Error(this.message);
      error.name = this.name;
      this.stack = error.stack;
    }
    CustomError.prototype = Object.create(Error.prototype);
    
    try {
      throw new CustomError('foobar');
    }
    catch (e) {
      console.log('name:', e.name);
      console.log('message:', e.message);
      console.log('stack:', e.stack);
    }
    
        5
  •  7
  •   Dave    12 年前
    class NotImplementedError extends Error {
      constructor(message) {
        super(message);
        this.message = message;
      }
    }
    NotImplementedError.prototype.name = 'NotImplementedError';
    module.exports = NotImplementedError;
    

    try {
      var e = new NotImplementedError("NotImplementedError message");
      throw e;
    } catch (ex1) {
      console.log(ex1.stack);
      console.log("ex1 instanceof NotImplementedError = " + (ex1 instanceof NotImplementedError));
      console.log("ex1 instanceof Error = " + (ex1 instanceof Error));
      console.log("ex1.name = " + ex1.name);
      console.log("ex1.message = " + ex1.message);
    }
    

    它只是一个类表示 this 回答。

    输出

    NotImplementedError: NotImplementedError message
      ...stacktrace
    ex1 instanceof NotImplementedError = true
    ex1 instanceof Error = true
    ex1.name = NotImplementedError
    ex1.message = NotImplementedError message
    
        6
  •  6
  •   sinisterchipmunk    12 年前

    本节标准可以解释为什么 Error.apply

    15.11.1作为函数调用的错误构造函数

    当Error作为函数而不是构造函数调用时,它会创建和 初始化新的Error对象。因此,函数调用Error(…)是 相当于对象创建表达式new Error(…) 同样的论点。

    在这种情况下 Error 函数可能确定它没有被作为构造函数调用,因此它返回一个新的Error实例,而不是初始化 this 对象。

    使用以下代码进行测试似乎证明了这实际上是正在发生的事情:

    function NotImplementedError() { 
       var returned = Error.apply(this, arguments);
       console.log("returned.message = '" + returned.message + "'");
       console.log("this.message = '" + this.message + "'");
    }
    NotImplementedError.prototype = new Error();
    
    var nie = new NotImplementedError("some message");
    

    运行此命令时会生成以下输出:

    returned.message = 'some message'
    this.message = ''
    
        7
  •  6
  •   Pierre Voisin    11 年前

    我喜欢这样做:

    • 利用 name 所以toString()抛出 "{code}: {message}"
    • 将相同的内容返回给super,使其在stacktrace中显示相同
    • 将代码附加到 error.code 因为检查/解析代码比检查消息更好,例如,您可能希望对消息进行本地化
    • 将邮件附加到 error.message 作为替代方案 error.toString()

    class AppException extends Error {
      constructor(code, message) {
        const fullMsg = message ? `${code}: ${message}` : code;
        super(fullMsg);
        this.name = code;
        this.code = code;
        this.message = fullMsg;
      }
      
      toString() {
        return this.message;
      }
    }
    
    // Just a code
    try {
      throw new AppException('FORBIDDEN');
    } catch(e) {
      console.error(e);
      console.error(e.toString());
      console.log(e.code === 'FORBIDDEN');
    }
    
    // A code and a message
    try {
      throw new AppException('FORBIDDEN', 'You don\'t have access to this page');
    } catch(e) {
      console.error(e);
      console.error(e.toString());
      console.log(e.code === 'FORBIDDEN');
    }
        8
  •  4
  •   borisdiakur Faheel Khan    7 年前
    function InvalidValueError(value, type) {
        this.message = "Expected `" + type.name + "`: " + value;
        var error = new Error(this.message);
        this.stack = error.stack;
    }
    InvalidValueError.prototype = new Error();
    InvalidValueError.prototype.name = InvalidValueError.name;
    InvalidValueError.prototype.constructor = InvalidValueError;
    
        9
  •  2
  •   Jules    13 年前

    Accoring to Joyent 你不应该弄乱stack属性(我在这里给出的很多答案中都看到了),因为它会对性能产生负面影响。他们是这么说的:

    一般来说,不要惹这个。甚至不要增加它。V8只在有人实际读取属性时才计算它,这大大提高了可处理错误的性能。如果你阅读属性只是为了增强它,即使你的调用者不需要堆栈,你最终也会支付费用。

    their idea of wrapping the original error 这是传递堆栈的一个很好的替代品。

    考虑到上述情况,以下是我创建自定义错误的方法:

    es5版本:

    function RError(options) {
        options = options || {}; // eslint-disable-line no-param-reassign
        this.name = options.name;
        this.message = options.message;
        this.cause = options.cause;
    
        // capture stack (this property is supposed to be treated as private)
        this._err = new Error();
    
        // create an iterable chain
        this.chain = this.cause ? [this].concat(this.cause.chain) : [this];
    }
    RError.prototype = Object.create(Error.prototype, {
        constructor: {
            value: RError,
            writable: true,
            configurable: true
        }
    });
    
    Object.defineProperty(RError.prototype, 'stack', {
        get: function stack() {
            return this.name + ': ' + this.message + '\n' + this._err.stack.split('\n').slice(2).join('\n');
        }
    });
    
    Object.defineProperty(RError.prototype, 'why', {
        get: function why() {
            var _why = this.name + ': ' + this.message;
            for (var i = 1; i < this.chain.length; i++) {
                var e = this.chain[i];
                _why += ' <- ' + e.name + ': ' + e.message;
            }
            return _why;
        }
    });
    
    // usage
    
    function fail() {
        throw new RError({
            name: 'BAR',
            message: 'I messed up.'
        });
    }
    
    function failFurther() {
        try {
            fail();
        } catch (err) {
            throw new RError({
                name: 'FOO',
                message: 'Something went wrong.',
                cause: err
            });
        }
    }
    
    try {
        failFurther();
    } catch (err) {
        console.error(err.why);
        console.error(err.stack);
        console.error(err.cause.stack);
    }

    es6版本:

    class RError extends Error {
        constructor({name, message, cause}) {
            super();
            this.name = name;
            this.message = message;
            this.cause = cause;
        }
        [Symbol.iterator]() {
            let current = this;
            let done = false;
            const iterator = {
                next() {
                    const val = current;
                    if (done) {
                        return { value: val, done: true };
                    }
                    current = current.cause;
                    if (!val.cause) {
                        done = true;
                    }
                    return { value: val, done: false };
                }
            };
            return iterator;
        }
        get why() {
            let _why = '';
            for (const e of this) {
                _why += `${_why.length ? ' <- ' : ''}${e.name}: ${e.message}`;
            }
            return _why;
        }
    }
    
    // usage
    
    function fail() {
        throw new RError({
            name: 'BAR',
            message: 'I messed up.'
        });
    }
    
    function failFurther() {
        try {
            fail();
        } catch (err) {
            throw new RError({
                name: 'FOO',
                message: 'Something went wrong.',
                cause: err
            });
        }
    }
    
    try {
        failFurther();
    } catch (err) {
        console.error(err.why);
        console.error(err.stack);
        console.error(err.cause.stack);
    }

    我已经将我的解决方案放入了一个模块中,如下所示: https://www.npmjs.com/package/rerror

        10
  •  2
  •   jherax    8 年前

    我也有类似的问题。我的错误必须是 instanceof 两者 Error NotImplemented ,它还需要在控制台中产生连贯的回溯。

    我的解决方案:

    var NotImplemented = (function() {
      var NotImplemented, err;
      NotImplemented = (function() {
        function NotImplemented(message) {
          var err;
          err = new Error(message);
          err.name = "NotImplemented";
          this.message = err.message;
          if (err.stack) this.stack = err.stack;
        }
        return NotImplemented;
      })();
      err = new Error();
      err.name = "NotImplemented";
      NotImplemented.prototype = err;
    
      return NotImplemented;
    }).call(this);
    
    // TEST:
    console.log("instanceof Error: " + (new NotImplemented() instanceof Error));
    console.log("instanceof NotImplemented: " + (new NotImplemented() instanceofNotImplemented));
    console.log("message: "+(new NotImplemented('I was too busy').message));
    throw new NotImplemented("just didn't feel like it");
    

    使用node.js运行的结果:

    instanceof Error: true
    instanceof NotImplemented: true
    message: I was too busy
    
    /private/tmp/t.js:24
    throw new NotImplemented("just didn't feel like it");
          ^
    NotImplemented: just didn't feel like it
        at Error.NotImplemented (/Users/colin/projects/gems/jax/t.js:6:13)
        at Object.<anonymous> (/Users/colin/projects/gems/jax/t.js:24:7)
        at Module._compile (module.js:449:26)
        at Object.Module._extensions..js (module.js:467:10)
        at Module.load (module.js:356:32)
        at Function.Module._load (module.js:312:12)
        at Module.runMain (module.js:487:10)
        at process.startup.processNextTick.process._tickCallback (node.js:244:9)
    

    该错误符合我的所有3个标准,尽管 stack 属性不标准, it is supported in most newer browsers 这对我来说是可以接受的。

        11
  •  1
  •   pluckyglen    16 年前

    我使用构造函数模式创建了新的错误对象。我定义了 原型链 例如a Error Error constructor 参考。

    您可以在此处查看此代码段 gist .

    实施

    // Creates user-defined exceptions
    var CustomError = (function() {
      'use strict';
    
      //constructor
      function CustomError() {
        //enforces 'new' instance
        if (!(this instanceof CustomError)) {
          return new CustomError(arguments);
        }
        var error,
          //handles the arguments object when is passed by enforcing a 'new' instance
          args = Array.apply(null, typeof arguments[0] === 'object' ? arguments[0] : arguments),
          message = args.shift() || 'An exception has occurred';
    
        //builds the message with multiple arguments
        if (~message.indexOf('}')) {
          args.forEach(function(arg, i) {
            message = message.replace(RegExp('\\{' + i + '}', 'g'), arg);
          });
        }
    
        //gets the exception stack
        error = new Error(message);
        //access to CustomError.prototype.name
        error.name = this.name;
    
        //set the properties of the instance
        //in order to resemble an Error instance
        Object.defineProperties(this, {
          stack: {
            enumerable: false,
            get: function() { return error.stack; }
          },
          message: {
            enumerable: false,
            value: message
          }
        });
      }
    
      // Creates the prototype and prevents the direct reference to Error.prototype;
      // Not used new Error() here because an exception would be raised here,
      // but we need to raise the exception when CustomError instance is created.
      CustomError.prototype = Object.create(Error.prototype, {
        //fixes the link to the constructor (ES5)
        constructor: setDescriptor(CustomError),
        name: setDescriptor('JSU Error')
      });
    
      function setDescriptor(value) {
        return {
          configurable: false,
          enumerable: false,
          writable: false,
          value: value
        };
      }
    
      //returns the constructor
      return CustomError;
    }());
    

    用法

    CustomError构造函数可以接收许多参数来构建消息,例如。

    var err1 = new CustomError("The url of file is required"),
        err2 = new CustomError("Invalid Date: {0}", +"date"),
        err3 = new CustomError("The length must be greater than {0}", 4),
        err4 = new CustomError("Properties .{0} and .{1} don't exist", "p1", "p2");
    
    throw err4;
    

    这就是自定义错误的外观:

    Custom error prototype chain

        12
  •  1
  •   Aram Kocharyan    11 年前

    这是我的实现:

    class HttpError extends Error {
      constructor(message, code = null, status = null, stack = null, name = null) {
        super();
        this.message = message;
        this.status = 500;
    
        this.name = name || this.constructor.name;
        this.code = code || `E_${this.name.toUpperCase()}`;
        this.stack = stack || null;
      }
    
      static fromObject(error) {
        if (error instanceof HttpError) {
          return error;
        }
        else {
          const { message, code, status, stack } = error;
          return new ServerError(message, code, status, stack, error.constructor.name);
        }
      }
    
      expose() {
        if (this instanceof ClientError) {
          return { ...this };
        }
        else {
          return {
            name: this.name,
            code: this.code,
            status: this.status,
          }
        }
      }
    }
    
    class ServerError extends HttpError {}
    
    class ClientError extends HttpError { }
    
    class IncorrectCredentials extends ClientError {
      constructor(...args) {
        super(...args);
        this.status = 400;
      }
    }
    
    class ResourceNotFound extends ClientError {
      constructor(...args) {
        super(...args);
        this.status = 404;
      }
    }
    

    示例用法#1:

    app.use((req, res, next) => {
      try {
        invalidFunction();
      }
      catch (err) {
        const error = HttpError.fromObject(err);
        return res.status(error.status).send(error.expose());
      }
    });
    

    示例用法#2:

    router.post('/api/auth', async (req, res) => {
      try {
        const isLogged = await User.logIn(req.body.username, req.body.password);
    
        if (!isLogged) {
          throw new IncorrectCredentials('Incorrect username or password');
        }
        else {
          return res.status(200).send({
            token,
          });
        }
      }
      catch (err) {
        const error = HttpError.fromObject(err);
        return res.status(error.status).send(error.expose());
      }
    });
    
        13
  •  1
  •   Rafal Enden    7 年前

    我只需要实现这样的东西,就发现堆栈在我自己的错误实现中丢失了。我所要做的就是创建一个虚拟错误并从中检索堆栈:

    My.Error = function (message, innerException) {
        var err = new Error();
        this.stack = err.stack; // IMPORTANT!
        this.name = "Error";
        this.message = message;
        this.innerException = innerException;
    }
    My.Error.prototype = new Error();
    My.Error.prototype.constructor = My.Error;
    My.Error.prototype.toString = function (includeStackTrace) {
        var msg = this.message;
        var e = this.innerException;
        while (e) {
            msg += " The details are:\n" + e.message;
            e = e.innerException;
        }
        if (includeStackTrace) {
            msg += "\n\nStack Trace:\n\n" + this.stack;
        }
        return msg;
    }
    
        14
  •  0
  •   Gima    12 年前

    这在Cesium DeveloperError中实现得很好:

    以简化形式:

    var NotImplementedError = function(message) {
        this.name = 'NotImplementedError';
        this.message = message;
        this.stack = (new Error()).stack;
    }
    
    // Later on...
    
    throw new NotImplementedError();
    
        15
  •  0
  •   kleopatra Aji kattacherry    12 年前

    function NotImplementedError(message) { return new Error("Not implemented", message); }
    
    x = new NotImplementedError();
    

    虽然我不知道你为什么要这么做。为什么不直接使用 new Error... 自定义异常在JavaScript(或任何非类型化语言)中并没有真正增加多少。

        16
  •  0
  •   Owen Allen    10 年前

    以无法使用为代价 instanceof ,以下内容保留了原始堆栈跟踪,不使用任何非标准技巧。

    // the function itself
    var fixError = function(err, name) {
        err.name = name;
        return err;
    }
    
    // using the function
    try {
        throw fixError(new Error('custom error message'), 'CustomError');
    } catch (e) {
        if (e.name == 'CustomError')
            console.log('Wee! Custom Error! Msg:', e.message);
        else
            throw e; // unhandled. let it propagate upwards the call stack
    }
    
        17
  •  0
  •   nanobar    7 年前

    另一种选择可能不适用于所有环境。至少可以保证它在nodejs 0.8中工作 这种方法使用了一种非标准的方式来修改内部原型道具

    function myError(msg){ 
          var e = new Error(msg); 
          _this = this; 
          _this.__proto__.__proto__ = e;
    }
    
        18
  •  -1
  •   Augustus Kling    13 年前

    如果你正在使用Node/Chrome。以下代码片段将为您提供满足以下要求的扩展。

    • err instanceof Error
    • err instanceof CustomErrorType
    • console.log()返回 [CustomErrorType] 当使用消息创建时
    • console.log()返回 [CustomErrorType: message] 当创建时没有消息
    • throw/stack提供错误创建时的信息。
    • 将在Chrome、Safari、Firefox和IE 8+中通过实例检查,但在Chrome/Safari之外没有有效的堆栈。我对此没意见,因为我可以在Chrome中调试,但需要特定错误类型的代码仍然可以跨浏览器运行。 如果你只需要Node,你可以很容易地删除 if .

    片段

    var CustomErrorType = function(message) {
        if (Object.defineProperty) {
            Object.defineProperty(this, "message", {
                value : message || "",
                enumerable : false
            });
        } else {
            this.message = message;
        }
    
        if (Error.captureStackTrace) {
            Error.captureStackTrace(this, CustomErrorType);
        }
    }
    
    CustomErrorType.prototype = new Error();
    CustomErrorType.prototype.name = "CustomErrorType";
    

    用法

    var err = new CustomErrorType("foo");
    

    输出

    var err = new CustomErrorType("foo");
    console.log(err);
    console.log(err.stack);
    
    [CustomErrorType: foo]
    CustomErrorType: foo
        at Object.<anonymous> (/errorTest.js:27:12)
        at Module._compile (module.js:456:26)
        at Object.Module._extensions..js (module.js:474:10)
        at Module.load (module.js:356:32)
        at Function.Module._load (module.js:312:12)
        at Function.Module.runMain (module.js:497:10)
        at startup (node.js:119:16)
        at node.js:906:3
    
    /errorTest.js:30
            throw err;
                  ^
    CustomErrorType: foo
        at Object.<anonymous> (/errorTest.js:27:12)
        at Module._compile (module.js:456:26)
        at Object.Module._extensions..js (module.js:474:10)
        at Module.load (module.js:356:32)
        at Function.Module._load (module.js:312:12)
        at Function.Module.runMain (module.js:497:10)
        at startup (node.js:119:16)
        at node.js:906:3
    
        19
  •  -3
  •   Paulo Enmanuel    12 年前

    以下内容摘自Mozilla官方文档,对我有效 Error .

    function NotImplementedError(message) {
        var instance = new Error(message);
        instance.name = 'NotImplementedError';
    
        Object.setPrototypeOf(instance, Object.getPrototypeOf(this));
        if (Error.captureStackTrace) {
            Error.captureStackTrace(instance, NotImplementedError);
        }
        return instance;
    }
    
    NotImplementedError.prototype = Object.create(Error.prototype, {
        constructor: {
            value: Error,
            enumerable: false,
            writable: true,
            configurable: true
        }
    });
    
        20
  •  -3
  •   Ronnie Smith    8 年前

    这是我支持es2015之前浏览器的解决方案。它不做任何花哨的原型调整,也不会破坏调试器。

    /**  Custom Errors
        // Depends on underscore js
        // This will declare an CustError() class in both 'this' and '_exports' namespaces
        // ctor is optional
        declare_cust_error(function CustError(){}, {ns: [this, _exports], ctor: 
            function cust_err_ctor(instance, clazz, name, msg, info){
                q$.called(arguments)
            }
        })
    
        // Usage:
        // Second param (pojso) is optional
        try {
            throw CustError.create("foo", {k1: 'v1', k2: 'v2'})
        }catch(ex){
            if(CustError.is_inst(ex)){
                console.error("its a CustError", ex)
            } else {
                throw ex
            }
        }
    
    **/
    function declare_cust_error(error_class, opts){
        var p, c, cp
        if(!error_class||!(p=error_class.prototype))throw new Error("error_class must be a Class")
        try{
            c = p.constructor; cp = c.toString()
        }catch(ex){}
        if(!cp || cp.indexOf('function ') != 0 || cp.indexOf('[native code]') > 0)
            throw new Error("error_class must be a classic proto class (pre-es6) but got: " + error_class.toString())
    
        opts=opts||{}
        
        error_class.__is_cust_error__ = true
        error_class.__cust_error_name__ = c.name
    
        error_class.create = function cust_error_create(msg, info){
            var instance = new Error(msg)
            instance.info = info
            instance.__is_cust_error__ = true
            instance.__cust_error_name__ = c.name
            if(_.isFunction(opts.ctor)){
                opts.ctor(instance, error_class, c.name, msg, info)
            }
            return instance
        }
    
        error_class.is_inst = function cust_error_is_inst(instanace){
            return ( (instanace instanceof Error) && instanace.__cust_error_name__ === error_class.__cust_error_name__ )
        }
        
        // Declare error in namespace(s)
        _.each(_.isArray(opts.ns)?opts.ns:[opts.ns], function(ns){ ns[c.name] = error_class })
    
        return error_class
    
    }