Como crio um erro personalizado em JavaScript?


215

Por alguma razão, parece que a delegação de construtores não funciona no seguinte trecho:

function NotImplementedError() { 
  Error.apply(this, arguments); 
}
NotImplementedError.prototype = new Error();

var nie = new NotImplementedError("some message");
console.log("The message is: '"+nie.message+"'")

Executando isso dá The message is: ''. Alguma idéia do porquê ou se existe uma maneira melhor de criar uma nova Errorsubclasse? Existe algum problema com applyo Errorconstrutor nativo que eu não conheça?


A instância da asserção NotImplementedError funciona após as alterações? Eu pensei que, para que isso funcione, você precisa definir o NotImplementedError.prototype.constructor explicitamente.
jayarjo

Da próxima vez, retire todo o código estranho que não é necessário para demonstrar seu problema. Além disso, o wtc é js.jar? Isso é necessário para reproduzir o problema?
BT

2
Editou esta pergunta para que seja compreensível em 10 segundos em vez de 10 minutos
BT

Eu criei uma biblioteca herança / classe que herda de tipos de erro corretamente: github.com/fresheneesz/proto
BT

1
jsfiddle para algumas das principais respostas.
Nate

Respostas:


194

Atualize seu código para atribuir seu protótipo ao erro.protótipo e a instânciaof e suas declarações funcionam.

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

No entanto, eu jogaria seu próprio objeto e apenas verificaria a propriedade name.

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

Editar com base nos comentários

Depois de analisar os comentários e tentar lembrar por que atribuiria um protótipo, em Error.prototypevez de new Error()como Nicholas Zakas fez em seu artigo , criei um jsFiddle com o código abaixo:

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);
}

A saída do console foi essa.

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

Isso confirma que o "problema" em que encontrei era a propriedade da pilha do erro, era o número da linha onde new Error()foi criado e não onde throw eocorreu. No entanto, isso pode ser melhor do que o efeito colateral de uma NotImplementedError.prototype.name = "NotImplementedError"linha que afeta o objeto Error.

Além disso, observe que NotImplementedError2, quando não defino .nameexplicitamente, é igual a "Erro". No entanto, conforme mencionado nos comentários, porque essa versão define o protótipo para new Error(), eu poderia definir NotImplementedError2.prototype.name = "NotImplementedError2"e ficar OK.


45
Melhor resposta, mas aceitar Error.prototypediretamente é provavelmente uma má forma. Se você quiser adicionar um nome NotImplementedError.prototype.toStringalternativo para o objeto agora Error.prototype.toString- melhor fazer NotImplementedError.prototype = new Error().
Cdleary # 1/10

4
Ainda estou um pouco perdido em todas essas coisas de protótipo. Por que no seu exemplo você atribui um nome a this.name e não a NotImplementedError.prototype.name? Você pode responder, por favor, é crucial para o meu entendimento :)
jayarjo

27
De acordo com code.google.com/p/chromium/issues/detail?id=228909 subclass.prototype = new Error() é uma forma incorreta. Você deveria usar em seu subclass.prototype = Object.create(superclass.prototype)lugar. Espero que ele possa corrigir o problema de rastreamento de pilha também.
Gili

8
Um truque simples para obter um rastreamento de pilha significativo é gerar erro no construtor e salvá-lo na pilha. Daria pilha de chamadas adequada + 1 linha para o construtor (é um pagamento adequado):this.stack = new Error().stack;
Meredian

6
-1; isto está errado. Fazer NotImplementedError.prototype = Error.prototype;não faz instanceoftratar NotImplementedErrorcomo uma subclasse de Error, faz instanceoftratá-los como exatamente a mesma classe. Se você colar o código acima no console e tentar new Error() instanceof NotImplementedErrorobter true, o que está claramente errado.
Mark Amery

87

Todas as respostas acima são terríveis - realmente. Mesmo aquele com 107 ups! A resposta real é aqui pessoal:

Herdando do objeto Error - onde está a propriedade message?

TL; DR:

R. O motivo messagenão está sendo definido é que Erroré uma função que retorna um novo objeto Error e não manipula de thisforma alguma.

B. A maneira de fazer isso direito é retornar o resultado da aplicação do construtor, além de definir o protótipo da maneira complicada e comum de javascripty:

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();
*/

Você provavelmente poderia fazer alguns truques para enumerar todas as propriedades não enumeráveis ​​do tmpErro para defini-las, em vez de definir apenas explicitamente apenas stacke message, mas a truque não é suportada em, por exemplo, <9


2
Essa solução também funciona para instanciar um erro personalizado com um erro existente. Se você estiver usando uma biblioteca de terceiros e quiser quebrar um erro existente com seu próprio tipo personalizado, os outros métodos não funcionarão corretamente. Para sua informação, você pode instanciar erros de baunilha passando a eles um erro existente.
Kyle Mueller

1
você não deveria return thisem um construtor.
Onur Yıldırım

13
I simplificado e melhorado esta abordagem um pouco: jsbin.com/rolojuhuya/1/edit?js,console
Matt Kantor

3
@ MattKantor talvez faça disso uma resposta? Acho que gosto mais do seu.
mpoisot

2
Em vez de temp.name = this.name = 'MyError', você pode fazer temp.name = this.name = this.constructor.name. Dessa forma, também funcionará para subclasses MyError.
Jo Liss

45

No ES2015, você pode classfazer isso de forma limpa:

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

Isto não modifica o mundial Errorprotótipo, permite personalizar message, namee outros atributos, e capta adequadamente a pilha. Também é bastante legível.

Obviamente, talvez você precise usar uma ferramenta como babelse seu código estivesse sendo executado em navegadores mais antigos.


23

Se alguém estiver curioso sobre como criar um erro personalizado e obter o rastreamento de pilha:

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);
}

7

Esta seção do padrão pode explicar por que a Error.applychamada não inicializa o objeto:

15.11.1 O construtor de erros chamado como uma função

Quando o erro é chamado como uma função e não como um construtor, ele cria e inicializa um novo objeto de erro. Portanto, a chamada de função Error (...) é equivalente à expressão de criação de objeto new Error (...) com os mesmos argumentos.

Nesse caso, a Errorfunção provavelmente determina que não está sendo chamada como construtora, portanto, retorna uma nova instância de Erro, em vez de inicializar o thisobjeto.

Testar com o código a seguir parece demonstrar que isso é realmente o que está acontecendo:

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");

A seguinte saída é gerada quando isso é executado:

returned.message = 'some message'
this.message = ''

como isso pode ser simulado com uma classe de erro personalizada? Por exemplo, como minha classe de erro personalizada pode ser usada como uma função que cria uma instância e como um construtor?
Lea Hayes

Não, isto não é verdade. Se ele retornasse uma nova instância de Erro, sua propriedade msg funcionaria.
BT

@BT Como a propriedade msg na nova instância afeta a propriedade msg thisno Error.apply(this, arguments);? Estou dizendo que a chamada para Error aqui está construindo um novo objeto, que é jogado fora; não inicializando o objeto já construído ao qual está atribuído nie.
Dave

@ BT Eu adicionei um código de exemplo que, com sorte, torna mais claro o que eu estava tentando dizer.
Dave

@ Dave Talvez eu tenha entendido mal o objetivo aqui, mas sua NotImplementedErrorimplementação não deve retornar a returnedvariável?
BLONG

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;

3
Esta é a melhor resposta aqui. É succint e a exceção criada dessa maneira se comportará corretamente em todas as situações. Ele também preserva o rastreamento de pilha, o que é muito importante em aplicativos não triviais. Eu substituiria apenas "prototype = new Error ()" por "prototype = Object.create (Error.prototype)". Para Node.js há uma pequena biblioteca que faz isso para você: npmjs.com/package/node-custom-errors
Lukasz Korzybski

6

Eu tive um problema semelhante a isso. Minhas necessidades de erro a ser um instanceoftanto Errore NotImplemented, e ele também precisa produzir um backtrace coerente no console.

Minha solução:

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");

Resultado da execução com o 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)

O erro passa todos os três dos meus critérios e, embora a stackpropriedade não seja padrão, ela é suportada na maioria dos navegadores mais novos, o que é aceitável no meu caso.


5

De acordo com Joyent, você não deve mexer com a propriedade stack (que vejo em muitas respostas aqui), porque isso terá um impacto negativo no desempenho. Aqui está o que eles dizem:

pilha: geralmente, não mexa com isso. Nem aumente. A V8 apenas calcula se alguém realmente lê a propriedade, o que melhora drasticamente o desempenho para erros de manuseio. Se você ler a propriedade apenas para aumentá-la, você acabará pagando o custo, mesmo que o chamador não precise da pilha.

Eu gosto e gostaria de mencionar a ideia deles de quebrar o erro original, que é um bom substituto para passar na pilha.

Então, aqui está como eu crio um erro personalizado, considerando o mencionado acima:

versão 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);
}

versão 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);
}

Coloquei minha solução em um módulo, aqui está: https://www.npmjs.com/package/rerror


3

Eu gosto de fazer assim:

  • Faça uso do nome para que toString () jogue"{code}: {message}"
  • Retorne a mesma coisa para super, para que ela pareça a mesma no stacktrace
  • Anexar código para error.codeverificar / analisar um código é melhor no código do que na verificação de uma mensagem, que você pode querer localizar, por exemplo
  • Anexe a mensagem error.messagecomo uma alternativa paraerror.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');
}


2

Eu apenas tive que implementar algo assim e descobri que a pilha estava perdida na minha própria implementação de erro. O que eu tive que fazer foi criar um erro fictício e recuperar a pilha a partir disso:

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;
}

Isso não define a mensagem
BT

2

Usei o Padrão do construtor para criar o novo objeto de erro. Eu defini a cadeia de protótipos , como uma Errorinstância. Consulte a referência do construtor MDN Error .

Você pode verificar este trecho nesta essência .

IMPLEMENTAÇÃO

// 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;
}());

USO

O construtor CustomError pode receber muitos argumentos para criar a mensagem, por exemplo

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;

E é assim que o erro personalizado se parece:

Cadeia de protótipo de erro personalizada


Quem votou mal, você tem argumentos ou motivo para votar? ou simplesmente não entende a intenção no código.
precisa saber é o seguinte

Acabei de notar que devo ter clicado no botão de votação acidentalmente enquanto navegava nesta página sem perceber (provavelmente navegando no meu telefone). Só notei hoje enquanto navegava na minha história. Definitivamente, não foi intencional, mas não posso desfazê-lo, pois é durante o período de carência. Você forneceu uma resposta informativa e definitivamente não a merece. Se você fizer uma edição, desfazerei felizmente o voto negativo. Me desculpe por isso.
jschr

1

O construtor precisa ser como um método de fábrica e retornar o que você deseja. Se você precisar de métodos / propriedades adicionais, poderá adicioná-los ao objeto antes de devolvê-lo.

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

x = new NotImplementedError();

Embora eu não tenha certeza do porquê você precisaria fazer isso. Por que não usar apenas new Error...? As exceções personalizadas realmente não adicionam muito em JavaScript (ou provavelmente em qualquer linguagem não digitada).


2
É necessário ativar a hierarquia do tipo de erro ou o valor do objeto no JavaScript, pois é possível especificar apenas um único bloco de captura. Na sua solução, (x instanceof NotImplementedError) é false, o que não é aceitável no meu caso.
cdleary

1

Isso é bem implementado no Cesium DeveloperError:

Em sua forma simplificada:

var NotImplementedError = function(message) {
    this.name = 'NotImplementedError';
    this.message = message;
    this.stack = (new Error()).stack;
}

// Later on...

throw new NotImplementedError();

Isso funciona muito bem, exceto que a pilha conterá uma linha extra para o construtor de erros, o que pode ser um problema.
SystemParadox

Além disso, não passa no error instanceof Errorteste, o que pode ser útil.
Lauren

1

Esta é a minha implementação:

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;
  }
}

Exemplo de uso nº 1:

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

Exemplo de uso nº 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());
  }
});

0

À custa de não poder usar instanceof, o seguinte preserva o rastreamento da pilha original e não usa nenhum truque não padrão.

// 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
}

Tudo que você precisa fazer aqui para ser capaz de usar instanceof é novo fixError lance em vez de apenas fixError
BT

@ BT: Não com a fixErrorfunção acima. Adicionar um newao chamar apenas criaria um objeto que é jogado fora.
TJ Crowder

Oh eu acho que eu quis dizer com "instanceof fixError" - é claro, em seguida, "instanceof erro" não iria funcionar .. eu acho que é pior ..
BT

0

Outra alternativa, pode não funcionar em todos os ambientes.

function myError(msg){ 
      var e = new Error(msg); 
      _this = this; 
      _this.__proto__.__proto__ = e;
}

0

Se você estiver usando o Node / Chrome. O snippet a seguir fornece uma extensão que atende aos seguintes requisitos.

  • err instanceof Error
  • err instanceof CustomErrorType
  • console.log () retorna [CustomErrorType]quando criado com uma mensagem
  • console.log () retorna [CustomErrorType: message]quando criado sem uma mensagem
  • throw / stack fornece as informações no ponto em que o erro foi criado.
  • Funciona perfeitamente no Node.JS e no Chrome.
  • Passará na instância de verificações no Chrome, Safari, Firefox e IE 8+, mas não terá uma pilha válida fora do Chrome / Safari. Estou bem com isso porque posso depurar no chrome, mas o código que requer tipos de erro específicos ainda funcionará em vários navegadores. Se você precisar apenas do Node, poderá remover facilmente as ifinstruções e estará pronto .

Snippet

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";

Uso

var err = new CustomErrorType("foo");

Resultado

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

0

O seguinte funcionou para mim, retirado da documentação oficial do 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
    }
});

-1

Tente um novo objeto de protótipo para cada instância do tipo de erro definido pelo usuário. Ele permite que as instanceofverificações se comportem como de costume, mais o tipo e a mensagem são relatados corretamente no Firefox e V8 (Chome, nodejs).

function NotImplementedError(message){
    if(NotImplementedError.innercall===undefined){
        NotImplementedError.innercall = true;
        NotImplementedError.prototype = new Error(message);
        NotImplementedError.prototype.name = "NotImplementedError";
        NotImplementedError.prototype.constructor = NotImplementedError;

        return new NotImplementedError(message);
    }
    delete NotImplementedError.innercall;
}

Observe que uma entrada adicional precederá a pilha correta.


Não funciona Tente: var a = new NotImplementedError('a'), b = new NotImplementedError('b');. Agora a instanceof NotImplementedError == falseeb instanceof NotImplementedError == true
jjrv

-1

Esta é a maneira mais rápida de fazer isso:

    let thisVar = false

    if (thisVar === false) {
            throw new Error("thisVar is false. It should be true.")
    }

-3

maneira mais fácil. Você pode fazer com que seu objeto seja herdado do objeto Error. Exemplo:

function NotImplementError(message)
{
    this.message = message;
    Error.call();
    Error.call(message);
} 

o que estamos fazendo é usar a função call () que chama o construtor da classe Error; portanto, é basicamente a mesma coisa que implementar uma herança de classe em outras linguagens orientadas a objetos.


Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.