Las palabras anteriores
El manejo de errores es crucial para el desarrollo de aplicaciones web. No puede predecir posibles errores por adelantado, y las estrategias de recuperación no se pueden adoptar por adelantado, lo que puede conducir a una mala experiencia del usuario. Dado que cualquier error de JavaScript puede hacer que la página web sea inutilizable, como desarrollador, debe saber cuándo, por qué y qué sucederá. Este artículo presentará el mecanismo de manejo de errores en JavaScript en detalle
objeto de error
El objeto de error es un objeto que contiene información de error y es un objeto nativo de JavaScript. Cuando se produce un error durante el análisis o la ejecución del código, el motor JavaScript generará automáticamente y lanzará una instancia del objeto de error, y luego todo el programa se interrumpirá cuando ocurra el error.
console.log (t); // no capturado referenceError: t no está definido
ECMA-262 especifica que un objeto de error incluye dos propiedades: mensaje y nombre. El atributo del mensaje guarda el mensaje de error, mientras que el atributo de nombre guarda el tipo de error
La copia del código es la siguiente:
// Generalmente, use la instrucción Try-Catch para capturar errores
intentar{
t;
} catch (ex) {
console.log (ex.message); // t no está definido
console.log (ex.name); // referenceError
}
El navegador también amplió las propiedades del objeto de error y agregó otra información relevante. Entre ellos, el más implementado por los fabricantes de navegadores es el atributo de pila, que indica información de rastreo de pila (Safari no lo admite)
La copia del código es la siguiente:
intentar{
t;
} catch (ex) {
console.log (ex.stack); //@file: /// d: /wamp/www/form.html: 12: 2
}
Por supuesto, puede usar el constructor Error () para crear un objeto de error. Si se especifica el parámetro del mensaje, el objeto de error lo usará como propiedad de mensaje; Si no se especifica, utilizará una cadena predeterminada predefinida como el valor de la propiedad
La copia del código es la siguiente:
nuevo error ();
nuevo error (mensaje);
// Generalmente, use la declaración de lanzamiento para lanzar errores
Tirar un nuevo error ('prueba'); // Error no capturado: prueba
tirar un error nuevo (); // error no capturado
La copia del código es la siguiente:
función userError (mensaje) {
this.message = Mensaje;
this.name = "UserError";
}
UserError.prototype = new Error ();
UserError.prototype.constructor = userError;
Lanzar nuevo UserError ("ErrorMessage"); // no capturado UserError: errorMessage
Cuando el constructor de error () se llama directamente como una función sin usar el nuevo operador, su comportamiento es el mismo que cuando se llama al nuevo operador
La copia del código es la siguiente:
Error();
Error (mensaje);
Error de lanzamiento ('prueba'); // Error no capturado: prueba
Error de tirar (); // error no capturado
El objeto de error tiene un método toString (), que devuelve el atributo de mensaje del objeto de error.
La copia del código es la siguiente:
VAR test = new Error ('testError');
console.log (test.toString ()); // 'Error: testError'
Tipo de error
Hay muchos tipos de errores que pueden ocurrir durante la ejecución del código. Cada error tiene un tipo de error correspondiente, y cuando ocurre un error, se lanzará un objeto de error del tipo correspondiente. ECMA-262 define los siguientes 7 tipos de error:
La copia del código es la siguiente:
Error
Evalterror (error de evaluación)
RangeError (RangeError)
ReferenceError (error de referencia)
SyntaxError (error de sintaxis)
TypeError (error de tipo)
Urierror (error de uri)
Dónde, el error es el tipo de base, y otros tipos de error se heredan de este tipo. Por lo tanto, todos los tipos de error comparten un conjunto de las mismas propiedades. Los errores del tipo de error son raros, y si lo hay, también son arrojados por el navegador; El objetivo principal de este tipo base es que los desarrolladores arrojen errores personalizados.
【Evalterror (error de evaluación)】
Cuando la función eval no se ejecuta correctamente, se lanzará un error de evaluación. Este tipo de error ya no aparece en ES5, pero continuará siendo conservado para garantizar la compatibilidad con códigos anteriores.
【RangeError (RangeError)】
Se activará un error del tipo RangeError cuando un valor excede el rango correspondiente, principalmente incluido el exceder el rango de longitud de la matriz y excediendo el rango de valor de número.
La copia del código es la siguiente:
nueva matriz (-1); // no capturado RangeError: longitud de matriz no válida
nueva matriz (número.max_value); // no capturado RangeError: longitud de matriz no válida
(1234) .ToExponential (21); // no capturado RangeError: ToExPonential () El argumento debe estar entre 0 y 20
(1234) .ToExponential (-1); //// no capturado RangeError: el argumento toExponential () debe estar entre 0 y 20
【ReferenceError (error de referencia)】
ReferenceError se activará al referirse a una variable inexistente o un error de tipo LVALUE.
a; // no capturado referenceError: a no está definido
1 ++; // no capturado referenceError: expresión lateral de la izquierda inválida en la operación posterior
【SyntaxError (SyntaxError)】
Cuando no se cumplen las reglas de sintaxis, se lanzará un SyntaxError (error de sintaxis)
La copia del código es la siguiente:
// El nombre de la variable es incorrecto
var 1a; // syntaxError no capturado: número inesperado
// Soportes faltantes
console.log 'hello'); // sintaxerror no capturado: cadena inesperada
【TypeError (error de tipo)】
El error de tipo TypeError se causará cuando se almacenan tipos inesperados en variables o cuando se accedan a métodos inexistentes. Aunque las causas de los errores son diversas, en última instancia, se debe a que el tipo de variable no cumple con los requisitos al realizar un tipo específico de operación.
La copia del código es la siguiente:
var o = nuevo 10; // typeError no capturado: 10 no es un constructor
alerta ('nombre' en true); // typeError no capturado: no se puede usar 'en' operador para buscar 'nombre' en true
Función
【Urierror (error URI)】
Urierror es un error lanzado cuando los parámetros de las funciones relacionadas con URI son incorrectos. Involucra principalmente a seis funciones: Encodeuri (), Decodeuri (), CodeRiComponent (), DecodeuriComponent (), Escape () y Unescape ().
decodeuri ('%2'); // urierror: URI malformado
evento de error
Cualquier error que no se procese a través de Try-Catch activará el evento de error del objeto de la ventana
El evento de error puede recibir tres parámetros: mensaje de error, URL donde se encuentra el error y el número de línea. En la mayoría de los casos, solo los mensajes de error son útiles porque la URL solo proporciona la ubicación del documento, y el número de línea se refiere a una línea de código que puede ser del código JavaScript integrado o de un archivo externo.
Para especificar un controlador de eventos de error, puede usar la tecnología de nivel DOM0 o usar el formato estándar de los eventos de nivel DOM2
La copia del código es la siguiente:
// nivel dom0
window.onerror = function (mensaje, url, línea) {
alerta (mensaje);
}
// nivel DOM2
Window.adDeventListener ("Error", función (mensaje, url, línea) {
alerta (mensaje);
});
Si el navegador muestra un mensaje de error estándar depende del valor de retorno de OnError. Si el valor de retorno es falso, se muestra un mensaje de error en la consola; Si el valor de retorno es verdadero, no se muestra
La copia del código es la siguiente:
// La consola muestra un mensaje de error
window.onerror = function (mensaje, url, línea) {
alerta (mensaje);
devolver falso;
}
a;
// La consola no muestra mensaje de error
window.onerror = function (mensaje, url, línea) {
alerta (mensaje);
devolver verdadero;
}
a;
Este controlador de eventos es la última línea de defensa para evitar errores de informes del navegador. Idealmente, no debes usarlo siempre que sea posible. Siempre que pueda usar la instrucción Try-Catch de manera adecuada, no se entregarán errores al navegador y el evento de error no se activará.
La imagen también admite eventos de error. Mientras la URL en la característica SRC de la imagen no pueda devolver el formato de imagen reconocido, se activará un evento de error. En este momento, el evento de error sigue el formato DOM y devuelve un objeto de evento que se dirige a la imagen como objetivo
Aparece un cuadro de advertencia cuando se carga la imagen. Cuando ocurre un evento de error, el proceso de descarga de imágenes ha finalizado, lo que significa que no se puede descargar nuevamente.
La copia del código es la siguiente:
var imagen = nueva imagen ();
Image.src = 'smilex.gif';
image.oNerror = function (e) {
console.log (e);
}
Declaración y error de lanzamiento
La declaración de lanzamiento se usa para lanzar un error. Cuando se lanza un error, debe especificar un valor a la instrucción de lanzamiento. ¿Qué tipo es este valor? No hay requisito.
[Nota] El proceso de lanzar un error está bloqueado y el código posterior no se ejecutará
La copia del código es la siguiente:
tirar 12345;
arrojar 'hola mundo';
tirar verdad;
tirar {nombre: 'javascript'};
Puede usar la declaración de lanzamiento para lanzar un objeto de error manualmente
La copia del código es la siguiente:
arrojar un nuevo error ('algo malo sucedió');
arroje nuevo sintaxerror ('no me gusta su sintaxis');
arrojar nuevo typeError ('¿Para qué tipo de variable me llevas?');
arrojar nuevos RangeError ('Lo siento, simplemente no tienes el rango');
arrojar nuevo evalersor ('que no evalúa');
arrojar nuevo urierror ('Uri, ¿eres tú?');
arrojar nuevo referenceError ('no citó sus referencias correctamente');
El uso de las cadenas prototipo también puede crear tipos de errores personalizados heredando el error (las cadenas prototipo se introducen en el Capítulo 6). En este punto, debe especificar los atributos de nombre y mensaje para el tipo de error recién creado
El navegador trata los tipos de error personalizados heredados de un error al igual que otros tipos de error. Crear un error personalizado es útil si desea detectar el error que lanza y tratarlo de manera diferente al error del navegador.
La copia del código es la siguiente:
function CustomError (mensaje) {
this.name = 'CustomError';
this.message = Mensaje;
}
CustomError.prototype = new Error ();
tirar nuevo CustomError ('mi mensaje');
Cuando se encuentra una declaración de lanzamiento, el código dejará de ejecutarse de inmediato. El código continuará ejecutándose solo si una instrucción Try-Catch captura el valor lanzado.
Una explicación más detallada es: cuando se lanza una excepción, el intérprete de JavaScript detendrá inmediatamente la lógica que se ejecuta actualmente y saltará al controlador de excepción cercano. El controlador de excepción está escrito en la cláusula de captura de la declaración Try-Catch. Si el bloque de código que arroja la excepción no tiene una cláusula de captura asociada, el intérprete verificará el bloque de código cerrado de nivel superior para ver si tiene un controlador de excepción asociado. Y así sucesivamente hasta que se encuentre un controlador de excepción. Si la función que lanza la excepción no maneja su instrucción Try-Catch, la excepción se propagará hacia arriba al código que llama a la función. De esta manera, la excepción se propagará hacia arriba a lo largo de la estructura léxica del método JavaScript y la pila de llamadas. Si no se encuentra ningún controlador de excepción, JavaScript manejará la excepción como un error de programa e informará al usuario
Pruebe la declaración de captura y el error de captura
ECMA-262 Edition 3 presenta la declaración Try-Catch como una forma estándar de manejar las excepciones en JavaScript, utilizada para captar y manejar errores
Entre ellos, la cláusula de prueba define el bloque de código donde se encuentran las excepciones que deben procesarse. La cláusula de captura sigue la cláusula de prueba. Cuando se produce una excepción en algún lugar del bloque de prueba, se llama a la lógica del código dentro de la captura. La cláusula de captura es seguida por el bloque Finalmente, donde se coloca el código de limpieza. Independientemente de si se produce una excepción en el bloque TRY, la lógica dentro del bloque Finalmente siempre se ejecutará. Aunque Catch y finalmente son opcionales, la cláusula de prueba requiere que al menos uno de los dos forme una declaración completa con ella.
Todos los bloques de instrucción Try/Catch/Finalmente deben estar encerrados con aparatos ortopédicos. Se requieren aparatos ortopédicos aquí. Incluso si solo hay una declaración en la cláusula, los aparatos rizados no se pueden omitir.
intentar{
// En términos generales, el código aquí comenzará de principio a fin sin ningún problema
// pero a veces se lanza una excepción, ya sea directamente lanzada por la declaración de lanzamiento o indirectamente llamando a un método
} catch (e) {
// Si y solo si el bloque de instrucción de prueba se lanza una excepción, el código aquí se ejecutará
// Aquí puede obtener una referencia al objeto de error u otros valores lanzados por la variable local E
// El bloque de código aquí puede manejar esta excepción por alguna razón, o ignorar esta excepción, y también puede volver a retirar la excepción a través de la declaración de lanzamiento
} finalmente{
// Independientemente de si la declaración de prueba arroja una excepción, la lógica finalmente siempre se ejecutará. Las formas de finalizar el bloque de la declaración de prueba son:
// 1. Terminar normalmente, ejecute la última declaración del bloque de instrucción
// 2. Terminar a través de la declaración de descanso, continuar o devolver
// 3. Lanzar una excepción, la excepción es atrapada por la cláusula de captura
// 4. Lanzar una excepción, la excepción no se atrapa, continúa siendo propagada hacia arriba
}
En general, coloque todo el código que pueda arrojar errores en el bloque de instrucción de prueba y coloque el código utilizado para el manejo de errores en el bloque de captura
Si se produce algún código en el error de prueba de prueba, el proceso de ejecución del código saldrá inmediatamente y se ejecutará el bloque de captura. En este momento, el bloque de captura recibirá un objeto con mensaje de error. La información real contenida en este objeto variará de navegador a navegador, pero lo común es que hay un atributo de mensaje que almacena el mensaje de error
[Nota] Asegúrese de nombrar el objeto de error. Si lo vacía, se informará un error de sintaxis.
La copia del código es la siguiente:
intentar{
Q;
} capt (error) {
alerta (error.message); // Q no está definido
}
// SyntaxError sin capacitación: token inesperado)
intentar{
Q;
}atrapar(){
alerta (error.message);
}
Catch acepta un parámetro que indica el valor lanzado por el bloque de código de prueba
La copia del código es la siguiente:
function showit (excepción) {
intentar {
Tirar excepción;
} catch (e) {
console.log ('atrapado:'+ e);
}
}
Throwit (3); // atrapado: 3
Throwit ('hola'); // atrapado: hola
Throwit (nuevo error ('un error sucedido')); // atrapado: error: un error sucedió
Después de que el bloque de código de captura captura el error, el programa no se interrumpirá y continuará ejecutándose de acuerdo con el proceso normal.
La copia del código es la siguiente:
intentar{
tirar "error";
} catch (e) {
console.log (111);
}
console.log (222);
// 111
// 222
Para atrapar diferentes tipos de errores, se pueden agregar declaraciones de juicio al bloque de código de captura
La copia del código es la siguiente:
intentar {
foo.bar ();
} catch (e) {
if (e instancia de evalerRor) {
console.log (e.name + ":" + e.message);
} else if (e instanceOf rangeError) {
console.log (e.name + ":" + e.message);
}
// ...
}
Aunque la cláusula Finalmente es opcional en la instrucción Try-Catch, una vez que se usa la cláusula Finalmente, su código se ejecutará sin importar qué. En otras palabras, todo el código en el bloque de la declaración de prueba se ejecuta normalmente, y finalmente se ejecutarán cláusulas; Si el bloque de instrucciones de captura se ejecuta debido a un error, la cláusula finalmente aún se ejecutará. Mientras el código contenga finalmente las cláusulas, sin importar qué código esté contenido en el bloque de instrucción Try o Catch, o incluso la declaración de devolución, la ejecución de la cláusula finalmente no se prevenirá.
La copia del código es la siguiente:
// El error no se captura porque no hay un bloque de instrucciones de captura. Después de ejecutar el bloque de código finalmente, el programa se interrumpirá donde se lanza el error.
function cleanSup () {
intentar {
tirar un nuevo error ('Error ...');
console.log ('esta línea no será ejecutada');
} finalmente {
console.log ('trabajo de limpieza completo');
}
}
CleanSup ();
// Completa el trabajo de limpieza
// Error: algo salió mal ...
La copia del código es la siguiente:
función testFinnally () {
intentar{
regresar 2;
} capt (error) {
regresar 1;
} finalmente{
regresar 0;
}
}
testFinnally (); // 0
[Nota] El valor del recuento de la declaración de retorno se obtiene antes de que se ejecute el bloque de código finalmente.
La copia del código es la siguiente:
Var Count = 0;
function countUp () {
intentar {
recuento de retorno;
} finalmente {
contar ++;
}
}
countUp (); // 0
console.log (cuenta); // 1
La copia del código es la siguiente:
función f () {
intentar {
console.log (0);
arrojar "insecto";
} catch (e) {
console.log (1);
devolver verdadero; // Esta oración se habría retrasado hasta el final del bloque de código finalmente antes de la ejecución
console.log (2); // no se ejecutará
} finalmente {
console.log (3);
devolver falso; // Esta oración cubrirá la devolución anterior
console.log (4); // no se ejecutará
}
console.log (5); // no se ejecutará
}
resultado var = f ();
// 0
// 1
// 3
console.log (resultado); // falso
【Consejos】 Alcance de nivel de bloque
Un uso común de las declaraciones de captura de trY es crear ámbitos de nivel de bloque donde las variables declaradas son válidas dentro de la captura
ES6 presenta la palabra clave LET para crear un alcance de nivel de bloque para las variables que declara. Sin embargo, en la situación actual de ES3 y ES5, las declaraciones de captura de prueba a menudo se usan para lograr efectos similares
A partir del siguiente código, E solo existe dentro de la cláusula de captura, y se lanzará un error al intentar hacer referencia desde otro lugar.
La copia del código es la siguiente:
intentar{
tirar un error nuevo (); // superar un error
} catch (e) {
console.log (e); // error (...)
}
console.log (e); // no capturado referenceError: e no está definido
Errores comunes
El núcleo del manejo de errores es saber primero qué errores ocurrirán en el código. Dado que JavaScript se escribe libremente y no verifica los parámetros de la función, el error solo ocurrirá durante el código. En términos generales, se deben prestar tres tipos de errores a: error de conversión de tipo, error de tipo de datos y error de comunicación
【Tipo de error de conversión】
El error de conversión de tipo ocurre cuando se usa un operador, o se usa otra estructura de lenguaje de los tipos de datos que pueden convertir automáticamente los valores.
La declaración de control de flujo es propensa a los errores de conversión de tipo. Declaraciones como si convertirán automáticamente algún valor a un booleano antes de determinar la siguiente operación. Especialmente si las declaraciones, si se usan de manera incorrecta, es más probable que cometan errores.
Las variables nombradas no utilizadas se asignan automáticamente valores indefinidos. El valor indefinido se puede convertir a un valor booleano falso, por lo que la instrucción IF en la siguiente función en realidad solo es aplicable a los casos en los que se proporciona el tercer parámetro. El problema es que no solo está indefinido para convertirse en falso, ni solo son valores de cadena los que pueden convertirse en verdadero. Por ejemplo, si el tercer parámetro es el valor 0, la prueba de la instrucción if fallará y la prueba del valor logarítmico 1 pasará
La copia del código es la siguiente:
función concat (str1, str2, str3) {
resultado var = str1 + str2;
if (str3) {// Absolutamente no como esto
resultado += str3;
}
resultado de retorno;
}
El uso de valores no booleanos en las declaraciones de control de flujo es una fuente extremadamente común de errores. Para evitar tales errores, es necesario pasar en valores booleanos cuando se comparan las condiciones. De hecho, realizar alguna forma de comparación puede lograr esto
La copia del código es la siguiente:
función concat (str1, str2, str3) {
resultado var = str1 + str2;
if (typeof str3 == 'string') {// más adecuado
resultado += str3;
}
resultado de retorno;
}
【Error de tipo de datos】
JavaScript se escribe libremente y no se comparará para garantizar que su tipo de datos sea correcto hasta que se usen variables y parámetros de función. Para garantizar que los errores de tipo de datos no ocurran, solo se puede escribir el código de detección de tipo de datos apropiado. Es más probable que ocurran errores de tipo de datos al pasar valores inesperados para trazar funciones
La copia del código es la siguiente:
// Funciones no seguras, cualquier valor sin array causará errores
Reversión de funciones (valores) {
if (valores) {
valores.sort ();
valores.reverse ();
}
}
Otro error común es comparar los parámetros con valores nulos. Comparar con NULL solo asegura que los valores correspondientes no sean nulos y indefinidos. Para garantizar que el valor pasado sea válido, no es suficiente detectar valores nulos solo
La copia del código es la siguiente:
// Funciones no seguras, cualquier valor sin array causará errores
Reversión de funciones (valores) {
if (valores! = nulo) {
valores.sort ();
valores.reverse ();
}
}
Si se pasa un objeto que contiene el método sort () (en lugar de una matriz), pasará la detección, pero puede ocurrir un error al llamar a la función reversa ()
La copia del código es la siguiente:
// Funciones no seguras, cualquier valor sin array causará errores
Reversión de funciones (valores) {
if (typeof valores.sort == 'function') {
valores.sort ();
valores.reverse ();
}
}
En caso de que sepa exactamente en qué tipo debe transmitir, es mejor usar instancia para detectar su tipo de datos
La copia del código es la siguiente:
// Se ignoran los valores seguros y sin matrices
Reversión de funciones (valores) {
if (instancia de valores de matriz) {
valores.sort ();
valores.reverse ();
}
}
【Error de comunicación】
Con el aumento de la programación AJAX, se ha convertido en un lugar común para que las aplicaciones web carguen dinámicamente la información o la funcionalidad durante su ciclo de vida. Sin embargo, cualquier comunicación entre JavaScript y el servidor puede causar un error
El problema más común es que los datos no están codificados utilizando EncodeUriComponent () antes de enviarlos al servidor
La copia del código es la siguiente:
//error
http://www.yourdomain.com/?redir=http://www.sometherdomain.com?a=b&c=d
// Llamar a CodeuricOponent () para todas las cadenas después de 'redir =' puede resolver este problema
http://www.yourdomain.com/?