As palavras anteriores
O tratamento de erros é crucial para o desenvolvimento de aplicativos da Web. Ele não pode prever possíveis erros com antecedência e as estratégias de recuperação não podem ser adotadas com antecedência, o que pode levar a uma experiência ruim do usuário. Como qualquer erro de JavaScript pode fazer com que a página da web seja inutilizável, como desenvolvedor, você deve saber quando, por que e o que acontecerá. Este artigo apresentará o mecanismo de manuseio de erros em JavaScript em detalhes
objeto de erro
O objeto de erro é um objeto que contém informações de erro e é um objeto nativo do JavaScript. Quando ocorre um erro durante a análise ou execução do código, o mecanismo JavaScript gera e lançará automaticamente uma instância do objeto de erro e, em seguida, o programa inteiro será interrompido quando o erro ocorre.
console.log (t); // Referência não capturada: t não é definida
O ECMA-262 especifica que um objeto de erro inclui duas propriedades: mensagem e nome. O atributo da mensagem salva a mensagem de erro, enquanto o atributo de nome salva o tipo de erro
A cópia do código é a seguinte:
// Geralmente, use a instrução Try-Catch para capturar erros
tentar{
t;
} catch (ex) {
console.log (Ex.Message); // t não é definido
console.log (Ex.Name); // ReferenceError
}
O navegador também expandiu as propriedades do objeto de erro e adicionou outras informações relevantes. Entre eles, o mais implementado pelos fabricantes de navegadores é o atributo de pilha, que indica informações de rastreamento de pilha (o Safari não o suporta)
A cópia do código é a seguinte:
tentar{
t;
} catch (ex) {
console.log (ex.stack); //@arquivo: /// d: /wamp/www/form.html: 12: 2
}
Obviamente, você pode usar o construtor Error () para criar um objeto de erro. Se o parâmetro da mensagem for especificado, o objeto de erro o usará como sua propriedade de mensagem; Se não for especificado, ele usará uma sequência padrão predefinida como o valor da propriedade
A cópia do código é a seguinte:
novo erro ();
novo erro (mensagem);
// Geralmente, use a declaração de arremesso para lançar erros
lançar um novo erro ('teste'); // erro não capturado: teste
lançar um novo erro (); // erro não capturado
A cópia do código é a seguinte:
função userError (mensagem) {
this.Message = message;
this.name = "userError";
}
UserError.prototype = new Error ();
UserError.prototype.Constructor = UserError;
Jogue novo UserError ("ErrorMessage"); // Userrror não capturado: errorMessage
Quando o construtor de erros () é chamado diretamente como uma função sem usar o novo operador, seu comportamento é o mesmo que quando o novo operador é chamado
A cópia do código é a seguinte:
Erro();
Erro (mensagem);
Erro de arremesso ('teste'); // Erro não capturado: teste
lança erro (); // erro não capturado
O objeto de erro possui um método tostring (), que retorna o atributo da mensagem do objeto de erro.
A cópia do código é a seguinte:
var teste = novo erro ('testError');
console.log (test.toString ()); // 'Erro: testError'
Tipo de erro
Existem muitos tipos de erros que podem ocorrer durante a execução do código. Cada erro tem um tipo de erro correspondente e, quando ocorre um erro, um objeto de erro do tipo correspondente será lançado. ECMA-262 define os 7 tipos de erro a seguir:
A cópia do código é a seguinte:
Erro
Avaliador (erro de avaliação)
RangeError (RangeError)
ReferenceError (erro de referência)
SyntaxError (erro de sintaxe)
TypeError (erro de tipo)
Urierror (erro de URI)
Onde o erro é o tipo base e outros tipos de erro são herdados desse tipo. Portanto, todos os tipos de erro compartilham um conjunto das mesmas propriedades. Os erros do tipo de erro são raros e, se houver, eles também são jogados pelo navegador; O principal objetivo deste tipo de base é que os desenvolvedores lançem erros personalizados
【Avaliador (erro de avaliação)】
Quando a função de avaliação não é executada corretamente, um erro de avaliação será lançado. Esse tipo de erro não aparece mais no ES5, mas continuará sendo preservado para garantir a compatibilidade com os códigos anteriores.
【RangeError (RangeError)】
Um erro do tipo RangeError será acionado quando um valor exceder o intervalo correspondente, incluindo principalmente excedendo a faixa de comprimento da matriz e excedendo o intervalo de valor numérico.
A cópia do código é a seguinte:
Nova matriz (-1); // RangeError não capturado: comprimento inválido da matriz
nova matriz (número.max_value); // não capturado rangeError: comprimento inválido da matriz
(1234) .toexponencial (21); // Uncathed RangeError: ToExponencial () O argumento deve estar entre 0 e 20
(1234) .toexponencial (-1); //// Uncathed RangeError: ToExponencial () O argumento deve estar entre 0 e 20
【ReferenceError (erro de referência)】
O ReferenceError será acionado ao se referir a uma variável não histórica ou erro do tipo LValue.
a; // ReferenceError não capturado: a não é definido
1 ++; // ReferenceError não capturado: expressão lateral de esquerda inválida na operação pós-fix
SyntaxError (SyntaxError)】
Quando as regras de sintaxe não forem atendidas, um SyntaxError será jogado (erro de sintaxe)
A cópia do código é a seguinte:
// O nome da variável está errado
var 1a; // sintaxeerror não capturado: número inesperado
// Patchets ausentes
console.log 'hello'); // SyntaxError não capturado: string inesperada
【TypeError (erro de tipo)】
O erro do tipo TypeError será causado quando tipos inesperados forem armazenados em variáveis ou ao acessar métodos inexistentes. Embora as causas dos erros sejam diversas, em última análise, é porque o tipo de variável não atende aos requisitos ao executar um tipo específico de operação.
A cópia do código é a seguinte:
var o = novo 10; // não -Esgot TypeError: 10 não é um construtor
alert ('nome' em true); // não -Esgot TypeError: não pode usar 'em' operador para pesquisar 'nome' em true
Function.prototype.toString.Call ('Nome'); // Uncathed TypeError: function.prototype.ToString não é genérico
【URIERROR (ERRO URI)】
Urierror é um erro lançado quando os parâmetros das funções relacionados a URI estão incorretos. Envolve principalmente seis funções: codeuri (), decodeuri (), codeuricomponent (), decodeuricomponent (), escape () e unescape ().
decodeuri ('%2'); // urierror: uri malformado
Evento de erro
Quaisquer erros que não sejam processados através do Try-Catch acionarão o evento de erro do objeto da janela
O evento de erro pode receber três parâmetros: mensagem de erro, URL onde o erro está localizado e o número da linha. Na maioria dos casos, apenas as mensagens de erro são úteis porque o URL apenas fornece a localização do documento, e o número da linha refere -se a uma linha de código que pode ser do código JavaScript incorporado ou de um arquivo externo.
Para especificar um manipulador de eventos de erro, você pode usar a tecnologia de nível DOM ou usar o formato padrão de eventos de nível DOM2
A cópia do código é a seguinte:
// DOM0 Nível
window.onerror = function (mensagem, url, linha) {
alerta (mensagem);
}
// Nível DOM2
window.addeventListener ("erro", função (mensagem, url, linha) {
alerta (mensagem);
});
Se o navegador exibe uma mensagem de erro padrão depende do valor de retorno do OnError. Se o valor de retorno for falso, uma mensagem de erro será exibida no console; Se o valor de retorno for verdadeiro, ele não será exibido
A cópia do código é a seguinte:
// Console exibe mensagem de erro
window.onerror = function (mensagem, url, linha) {
alerta (mensagem);
retornar falso;
}
um;
// O console não exibe mensagem de erro
window.onerror = function (mensagem, url, linha) {
alerta (mensagem);
retornar true;
}
um;
Este manipulador de eventos é a última linha de defesa para evitar erros de relatório do navegador. Idealmente, você não deve usá -lo sempre que possível. Contanto que você possa usar a instrução Try-Catch adequadamente, não haverá erros entregues ao navegador e o evento de erro não será acionado.
A imagem também suporta eventos de erro. Enquanto o URL na característica SRC da imagem não puder retornar o formato de imagem reconhecido, um evento de erro será acionado. No momento, o evento de erro segue o formato DOM e retorna um objeto de evento direcionado à imagem como o alvo
Uma caixa de aviso aparece quando a imagem é carregada. Quando ocorre um evento de erro, o processo de download da imagem terminou, o que significa que ele não pode ser baixado novamente.
A cópia do código é a seguinte:
Var Image = new Image ();
image.src = 'smilex.gif';
image.onerror = function (e) {
console.log (e);
}
Declaração de jogue e jogue erro
A declaração de arremesso é usada para lançar um erro. Quando um erro é lançado, você deve especificar um valor para a declaração de arremesso. Que tipo é esse valor? Não há requisito.
[Nota] O processo de lançamento de um erro é bloqueado e o código subsequente não será executado
A cópia do código é a seguinte:
jogue 12345;
jogue 'olá mundo';
jogue verdadeiro;
lançar {nome: 'javascript'};
Você pode usar a declaração de arremesso para lançar manualmente um objeto de erro
A cópia do código é a seguinte:
lançar um novo erro ('algo ruim aconteceu');
lançar uma nova sintaxerror ('eu não gosto da sua sintaxe.');
lançar um novo TypeError ('que tipo de variável você me leva?');
jogue novo RangeError ('Desculpe, você não tem o alcance');
lançar um novo avaliador ('que não avalia');
Jogue novo Urierror ('Uri, é você?');
jogue novo referenceError ('Você não citou suas referências corretamente');
O uso de cadeias de protótipo também pode criar tipos de erro personalizados herdando erros (as cadeias de protótipo são introduzidas no capítulo 6). Neste ponto, você precisa especificar o nome e os atributos da mensagem para o tipo de erro recém -criado
O navegador trata os tipos de erro personalizados herdados do erro, assim como outros tipos de erro. Criar um erro personalizado é útil se você deseja pegar o erro que você o trata e o trate de maneira diferente do erro do navegador.
A cópia do código é a seguinte:
Função CustomError (mensagem) {
this.name = 'CustomError';
this.Message = message;
}
CustomError.prototype = new Error ();
lançar novo CustomError ('minha mensagem');
Quando uma declaração de arremesso é encontrada, o código para de executar imediatamente. O código continuará sendo executado apenas se uma instrução Try-Catch capturar o valor jogado.
Uma explicação mais detalhada é: quando uma exceção é lançada, o intérprete JavaScript interrompe imediatamente a lógica atualmente em execução e pulará para o manipulador de exceção nas proximidades. O manipulador de exceção está escrito na cláusula de captura da instrução Try-Catch. Se o bloco de código que lança a exceção não tiver uma cláusula de captura associada, o intérprete verificará o bloco de código fechado de nível superior para ver se possui um manipulador de exceção associado. E assim por diante até que um manipulador de exceção seja encontrado. Se a função que lança a exceção não lidar com sua instrução Try-Catch, a exceção será propagada para cima para o código que chama a função. Dessa forma, a exceção será propagada para cima ao longo da estrutura lexical do método JavaScript e da pilha de chamadas. Se nenhum manipulador de exceção for encontrado, o JavaScript lidará com a exceção como erro de programa e o relatará ao usuário
Experimente a declaração de captura e o erro de captura
ECMA-262 Edição 3 apresenta a instrução Try-Catch como uma maneira padrão de lidar com exceções no JavaScript, usado para capturar e lidar com erros
Entre eles, a cláusula de tentativa define o bloco de código onde estão localizadas as exceções que precisam ser processadas. A cláusula de captura segue a cláusula de tentativa. Quando ocorre uma exceção em algum lugar do bloco de tentativa, a lógica do código dentro da captura é chamada. A cláusula de captura é seguida pelo bloco finalmente, onde o código de limpeza é colocado. Independentemente de ocorrer uma exceção no bloco de tentativas, a lógica dentro do bloco finalmente será sempre executada. Embora a captura e finalmente seja opcional, a cláusula de tentativa requer pelo menos um dos dois para formar uma declaração completa com ela.
Todos os blocos de tentativa/captura/finalmente precisam ser fechados com aparelhos encaracolados. Os aparelhos aqui são necessários. Mesmo se houver apenas uma declaração na cláusula, os aparelhos encaracolados não podem ser omitidos.
tentar{
// De um modo geral, o código aqui começará do começo ao fim sem problemas
// mas às vezes uma exceção é lançada, diretamente jogada pela declaração de arremesso ou indiretamente chamando um método
} catch (e) {
// se e somente se uma exceção for lançada pelo bloco de instrução Try, o código aqui será executado
// Aqui você pode obter uma referência ao objeto de erro ou a outros valores jogados pela variável local e
// O bloco de código aqui pode lidar com essa exceção por algum motivo ou ignorar essa exceção e também pode re-lingar a exceção através da instrução THOW
} finalmente{
// Independentemente de a declaração de tentativa lançar uma exceção, a lógica finalmente será sempre executada. As maneiras de encerrar o bloco de instrução Try são:
// 1. Rescindir normalmente, execute a última declaração do bloco de declaração
// 2. Encerrar a declaração de interrupção, continuação ou retorno
// 3. Jogue uma exceção, a exceção é capturada pela cláusula de captura
// 4. Jogue uma exceção, a exceção não é pega, continue sendo propagada para cima
}
Geralmente, coloque todo o código que possa lançar erros no bloco de instrução Try e coloque o código usado para manuseio de erros no bloco de captura
Se ocorrer algum código no erro de tentativa do bloco, o processo de execução do código será imediatamente saindo e o bloco de captura será executado. No momento, o bloco de captura receberá um objeto com mensagem de erro. As informações reais contidas neste objeto variam de navegador para navegador, mas o comum é que existe um atributo de mensagem que armazena a mensagem de erro
[Nota] Certifique -se de nomear o objeto de erro. Se esvaziá -lo, será relatado um erro de sintaxe.
A cópia do código é a seguinte:
tentar{
q;
} catch (erro) {
alerta (error.message); // q não é definido
}
// SyntaxError não capturado: token inesperado)
tentar{
q;
}pegar(){
alerta (error.message);
}
Catch aceita um parâmetro indicando o valor jogado pelo bloco de código de tentativa
A cópia do código é a seguinte:
função throwit (exceção) {
tentar {
Exceção de lançar;
} catch (e) {
console.log ('pego:'+ e);
}
}
throwit (3); // pego: 3
throwit ('hello'); // pego: Olá
throwit (novo erro ('um erro aconteceu')); // pego: erro: um erro aconteceu
Após o bloco de código de captura capturar o erro, o programa não será interrompido e continuará sendo executado de acordo com o processo normal.
A cópia do código é a seguinte:
tentar{
lançar "erro";
} catch (e) {
console.log (111);
}
console.log (222);
// 111
// 222
Para capturar diferentes tipos de erros, as declarações de julgamento podem ser adicionadas ao bloco de código de captura
A cópia do código é a seguinte:
tentar {
foo.bar ();
} catch (e) {
if (e instanceof avaliador) {
console.log (e.name + ":" + e.message);
} else if (e instanceof rangeError) {
console.log (e.name + ":" + e.message);
}
// ...
}
Embora a cláusula finalmente seja opcional na instrução Try-Catch, depois que a cláusula finalmente for usada, seu código será executado, não importa o quê. Em outras palavras, todo o código no bloco de instrução Try é executado normalmente e, finalmente, cláusulas serão executadas; Se o bloco de declaração de captura for executado devido a um erro, a cláusula finalmente ainda será executada. Enquanto o código contiver finalmente cláusulas, não importa qual código esteja contido no bloco de instrução TRY OR CATCH - ou mesmo a declaração de retorno, a execução da cláusula finalmente não será impedida.
A cópia do código é a seguinte:
// O erro não é capturado porque não há bloco de declaração de captura. Depois de executar o bloco de código finalmente, o programa será interrompido quando o erro é lançado.
função limpensup () {
tentar {
lançar um novo erro ('erro ...');
console.log ('Esta linha não será executada');
} finalmente {
console.log ('Trabalho completo de limpeza');
}
}
limpensup ();
// complete o trabalho de limpeza
// Erro: algo deu errado ...
A cópia do código é a seguinte:
function testfinnally () {
tentar{
retornar 2;
} catch (erro) {
retornar 1;
} finalmente{
retornar 0;
}
}
testFinnally (); // 0
[Nota] O valor da contagem da instrução Retorno é obtido antes que o bloco de código finalmente seja executado.
A cópia do código é a seguinte:
var count = 0;
function countup () {
tentar {
contagem de retorno;
} finalmente {
contagem ++;
}
}
Condep (); // 0
console.log (contagem); // 1
A cópia do código é a seguinte:
função f () {
tentar {
console.log (0);
lançar "bug";
} catch (e) {
console.log (1);
retornar true; // Esta frase teria sido adiada até o final do bloco de código finalmente antes da execução
console.log (2); // não vai correr
} finalmente {
console.log (3);
retornar falso; // Esta frase cobrirá o retorno anterior
console.log (4); // não vai correr
}
console.log (5); // não vai correr
}
var resultado = f ();
// 0
// 1
// 3
console.log (resultado); // false
【Dicas】 Escopo no nível do bloco
Um uso comum de declarações de tentativa é criar escopos de nível em bloco, onde as variáveis declaradas são válidas apenas dentro da captura
O ES6 apresenta a palavra-chave Let para criar um escopo de nível de bloco para as variáveis que declara. No entanto, na situação atual de ES3 e ES5, as declarações de tentativa são frequentemente usadas para alcançar efeitos semelhantes
A partir do código a seguir, E só existe dentro da cláusula de captura, e um erro será lançado ao tentar fazer referência a ele de outros lugares.
A cópia do código é a seguinte:
tentar{
lançar um novo erro (); // no topo de um erro
} catch (e) {
console.log (e); // erro (…)
}
console.log (e); // ReferenceError não capturado: e não é definido
Erros comuns
O núcleo do tratamento de erros é primeiro saber quais erros acontecerão no código. Como o JavaScript é pouco digitado e não verifica os parâmetros da função, o erro ocorrerá apenas durante o código. De um modo geral, três tipos de erros precisam receber atenção: TIPE ERRO DE CONVERSÃO, ERRO DE TIPO DE DADOS E ERRO DE COMUNICAÇÃO
Error de conversão Tipo】
O erro de conversão do tipo ocorre ao usar um operador ou usar outra estrutura de idioma dos tipos de dados que podem converter automaticamente valores.
A instrução de controle de fluxo é propensa a digitar erros de conversão. Declarações como se forem converter automaticamente qualquer valor em um booleano antes de determinar a próxima operação. Especialmente se as declarações, se usadas indevidamente, são mais propensas a cometer erros.
As variáveis nomeadas não utilizadas são automaticamente atribuídas valores indefinidos. O valor indefinido pode ser convertido em um valor booleano false; portanto, a instrução IF na função a seguir é realmente aplicável aos casos em que o terceiro parâmetro é fornecido. O problema é que ele não é apenas indefinido para ser convertido em falso, nem apenas os valores de string que podem ser convertidos em verdadeiros. Por exemplo, se o terceiro parâmetro for o valor 0, o teste da instrução IF falhará e o teste do valor logarítmico 1 passará
A cópia do código é a seguinte:
função concat (str1, str2, str3) {
var resultado = str1 + str2;
if (str3) {// absolutamente não assim
resultado += str3;
}
resultado de retorno;
}
O uso de valores não-booleanos em declarações de controle de fluxo é uma fonte extremamente comum de erros. Para evitar esses erros, é necessário passar nos valores booleanos quando as condições são comparadas. De fato, executar alguma forma de comparação pode conseguir isso
A cópia do código é a seguinte:
função concat (str1, str2, str3) {
var resultado = str1 + str2;
if (typeof str3 == 'string') {// mais adequado
resultado += str3;
}
resultado de retorno;
}
Error Tipo de dados Erro】
O JavaScript é digitado livremente e não será comparado para garantir que seu tipo de dados esteja correto até que variáveis e parâmetros de função sejam usados. Para garantir que os erros de tipo de dados não ocorram, apenas o código de detecção de tipo de dados apropriado pode ser gravado. É mais provável que os erros do tipo de dados ocorram ao passar valores inesperados para plotar funções
A cópia do código é a seguinte:
// Funções não seguras, qualquer valor que não seja provável cause erros
função reversa (valores) {
if (valores) {
valores.sort ();
valores.Reverse ();
}
}
Outro erro comum é comparar parâmetros com valores nulos. A comparação com o NULL garante apenas que os valores correspondentes não sejam nulos e indefinidos. Para garantir que o valor passado seja válido, não é suficiente para detectar valores nulos apenas
A cópia do código é a seguinte:
// Funções não seguras, qualquer valor que não seja provável cause erros
função reversa (valores) {
if (valores! = null) {
valores.sort ();
valores.Reverse ();
}
}
Se um objeto que contém o método Sort () (em vez de uma matriz) for aprovado, ele passará a detecção, mas pode ocorrer um erro ao chamar a função reverse ()
A cópia do código é a seguinte:
// Funções não seguras, qualquer valor que não seja provável cause erros
função reversa (valores) {
if (typeof valores.sort == 'function') {
valores.sort ();
valores.Reverse ();
}
}
Caso você saiba exatamente em que tipo você deve passar, é melhor usar a instância para detectar seu tipo de dados
A cópia do código é a seguinte:
// valores seguros e não-maiores são ignorados
função reversa (valores) {
if (valores instância de matriz) {
valores.sort ();
valores.Reverse ();
}
}
【Erro de comunicação】
Com o aumento da programação do AJAX, tornou -se comum os aplicativos da Web para carregar informações ou funcionalidade dinamicamente durante seu ciclo de vida. No entanto, qualquer comunicação entre JavaScript e o servidor pode causar um erro
O problema mais comum é que os dados não são codificados usando o codeuricomponent () antes de enviá -los para o servidor
A cópia do código é a seguinte:
//erro
http://www.yourdomain.com/?redir=http://www.sometherdomain.com?a=b&c=d
// Calling Codeuricomponent () para todas as cordas após 'redir =' pode resolver este problema
http://www.yourdomain.com/?redir=http:%3a%2f%2fwww.sometherdomeain.com%3fa%3DB%26C%3DD