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 Error
subclasse? Existe algum problema com apply
o Error
construtor nativo que eu não conheça?
javascript
exception
cdleary
fonte
fonte
Respostas:
Atualize seu código para atribuir seu protótipo ao erro.protótipo e a instânciaof e suas declarações funcionam.
No entanto, eu jogaria seu próprio objeto e apenas verificaria a propriedade name.
Editar com base nos comentários
Depois de analisar os comentários e tentar lembrar por que atribuiria um protótipo, em
Error.prototype
vez denew Error()
como Nicholas Zakas fez em seu artigo , criei um jsFiddle com o código abaixo:A saída do console foi essa.
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 ondethrow e
ocorreu. No entanto, isso pode ser melhor do que o efeito colateral de umaNotImplementedError.prototype.name = "NotImplementedError"
linha que afeta o objeto Error.Além disso, observe que
NotImplementedError2
, quando não defino.name
explicitamente, é igual a "Erro". No entanto, conforme mencionado nos comentários, porque essa versão define o protótipo paranew Error()
, eu poderia definirNotImplementedError2.prototype.name = "NotImplementedError2"
e ficar OK.fonte
Error.prototype
diretamente é provavelmente uma má forma. Se você quiser adicionar um nomeNotImplementedError.prototype.toString
alternativo para o objeto agoraError.prototype.toString
- melhor fazerNotImplementedError.prototype = new Error()
.subclass.prototype = new Error()
é uma forma incorreta. Você deveria usar em seusubclass.prototype = Object.create(superclass.prototype)
lugar. Espero que ele possa corrigir o problema de rastreamento de pilha também.this.stack = new Error().stack;
NotImplementedError.prototype = Error.prototype;
não fazinstanceof
tratarNotImplementedError
como uma subclasse deError
, fazinstanceof
tratá-los como exatamente a mesma classe. Se você colar o código acima no console e tentarnew Error() instanceof NotImplementedError
obtertrue
, o que está claramente errado.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
message
não está sendo definido é queError
é uma função que retorna um novo objeto Error e não manipula dethis
forma 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:
Você provavelmente poderia fazer alguns truques para enumerar todas as propriedades não enumeráveis do
tmp
Erro para defini-las, em vez de definir apenas explicitamente apenasstack
emessage
, mas a truque não é suportada em, por exemplo, <9fonte
return this
em um construtor.temp.name = this.name = 'MyError'
, você pode fazertemp.name = this.name = this.constructor.name
. Dessa forma, também funcionará para subclassesMyError
.No ES2015, você pode
class
fazer isso de forma limpa:Isto não modifica o mundial
Error
protótipo, permite personalizarmessage
,name
e outros atributos, e capta adequadamente a pilha. Também é bastante legível.Obviamente, talvez você precise usar uma ferramenta como
babel
se seu código estivesse sendo executado em navegadores mais antigos.fonte
Se alguém estiver curioso sobre como criar um erro personalizado e obter o rastreamento de pilha:
fonte
Esta seção do padrão pode explicar por que a
Error.apply
chamada não inicializa o objeto:Nesse caso, a
Error
função provavelmente determina que não está sendo chamada como construtora, portanto, retorna uma nova instância de Erro, em vez de inicializar othis
objeto.Testar com o código a seguir parece demonstrar que isso é realmente o que está acontecendo:
A seguinte saída é gerada quando isso é executado:
fonte
this
noError.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ídonie
.NotImplementedError
implementação não deve retornar areturned
variável?fonte
Eu tive um problema semelhante a isso. Minhas necessidades de erro a ser um
instanceof
tantoError
eNotImplemented
, e ele também precisa produzir um backtrace coerente no console.Minha solução:
Resultado da execução com o node.js:
O erro passa todos os três dos meus critérios e, embora a
stack
propriedade não seja padrão, ela é suportada na maioria dos navegadores mais novos, o que é aceitável no meu caso.fonte
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:
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:
versão es6:
Coloquei minha solução em um módulo, aqui está: https://www.npmjs.com/package/rerror
fonte
Eu gosto de fazer assim:
"{code}: {message}"
error.code
verificar / analisar um código é melhor no código do que na verificação de uma mensagem, que você pode querer localizar, por exemploerror.message
como uma alternativa paraerror.toString()
fonte
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:
fonte
Usei o Padrão do construtor para criar o novo objeto de erro. Eu defini a cadeia de protótipos , como uma
Error
instância. Consulte a referência do construtor MDN Error .Você pode verificar este trecho nesta essência .
IMPLEMENTAÇÃO
USO
O construtor CustomError pode receber muitos argumentos para criar a mensagem, por exemplo
E é assim que o erro personalizado se parece:
fonte
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.
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).fonte
Isso é bem implementado no Cesium DeveloperError:
Em sua forma simplificada:
fonte
error instanceof Error
teste, o que pode ser útil.Esta é a minha implementação:
Exemplo de uso nº 1:
Exemplo de uso nº 2:
fonte
À 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.fonte
fixError
função acima. Adicionar umnew
ao chamar apenas criaria um objeto que é jogado fora.Outra alternativa, pode não funcionar em todos os ambientes.
fonte
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
[CustomErrorType]
quando criado com uma mensagem[CustomErrorType: message]
quando criado sem uma mensagemif
instruções e estará pronto .Snippet
Uso
Resultado
fonte
O seguinte funcionou para mim, retirado da documentação oficial do Mozilla Error .
fonte
Tente um novo objeto de protótipo para cada instância do tipo de erro definido pelo usuário. Ele permite que as
instanceof
verificações se comportem como de costume, mais o tipo e a mensagem são relatados corretamente no Firefox e V8 (Chome, nodejs).Observe que uma entrada adicional precederá a pilha correta.
fonte
var a = new NotImplementedError('a'), b = new NotImplementedError('b');
. Agoraa instanceof NotImplementedError == false
eb instanceof NotImplementedError == true
Esta é a maneira mais rápida de fazer isso:
fonte
maneira mais fácil. Você pode fazer com que seu objeto seja herdado do objeto Error. Exemplo:
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.
fonte
MDN tem um excelente exemplo :
fonte