Control del flujo y manejo de errores
EsJs admite un compacto conjunto de declaraciones, específicamente declaraciones de control de flujo, que puedes utilizar para incorporar una gran cantidad de interactividad en tu aplicación. Esta sección proporciona una descripción de estas declaraciones.
Declaración de bloque
La declaración más básica es una declaración de bloque, que se utiliza para agrupar instrucciones. El bloque está delimitado por un par de llaves:
{
declaracion_1;
declaracion_2;
⋮
declaracion_n;
}
Las declaraciones de bloque se utilizan comúnmente con declaraciones de control de flujo (si
, para
, mientras
).
Ejemplo
El siguiente ejemplo comienza declarando una variable x
con el valor 0
. Luego, mientras x
sea menor que 10
, ejecuta el bloque de declaración del buclie mientras
, de manera que muestra en la consola los 10 números del Sistema Decimal:
En este ejemplo, la declaración de bloque es lo que está entre llaves:
{
consola.escribir(x);
x = x + 1; // Aumenta el valor de "x" para la siguiente iteración
}
Expresiones condicionales
Una expresión condicional es un conjunto de instrucciones que se ejecutarán si una condición especificada es verdadera. EsJS admite dos expresiones condicionales: si...sino
y elegir
.
Expresión si...sino
Utiliza la expresión si
para ejecutar una instrucción si una condición lógica es verdadero
. Utiliza la cláusula opcional sino
para ejecutar una instrucción si la condición es falso
.
Una declaración si
se ve así:
si (condicion) {
declaracion_1;
} sino {
declaracion_2;
}
Aquí, la condicion
puede ser cualquier expresión que se evalúe como verdadero
o falso
. (Consulta Booleano
para obtener una explicación de lo que se evalúa como verdadero
y falso
).
Si condicion
se evalúa como verdadero
, se ejecuta declaracion_1
. De lo contrario, se ejecuta declaracion_2
.
declaracion_1
y declaracion_2
pueden ser cualquier declaración, incluidas otras declaraciones si
anidadas.
También puedes componer las declaraciones usando sino si
para que se prueben varias condiciones en secuencia, de la siguiente manera:
si (condition_1) {
declaracion_1;
} sino si (condition_2) {
declaracion_2;
} sino si (condition_n) {
declaracion_n;
} sino {
declaracion_last;
}
En el caso de múltiples condiciones, solo se ejecutará la primera condición lógica que se evalúe como verdadero
.
Nota: Mejores prácticas: Aunque es posible, no es aconsejable utilizar asignaciones simples en una expresión condicional, porque la asignación se puede confundir con la igualdad al mirar el código.
Por ejemplo, no escribas un código como este:
Si necesitas usar una tarea en una expresión condicional, una práctica común es poner paréntesis adicionales alrededor de la asignación, así:
O mejor aún, mueve la expresión de asignación afuera de la expresión
si
, y sólo utiliza expresiones condicionales:
Valores falsos
Los siguientes valores se evalúan como falso
(también conocidos como valores Falsy (en-US):
falso
indefinido
nulo
0
NeN
- la cadena vacía (
""
)
Todos los demás valores, incluidos todos los objetos, se evalúan como verdadero
cuando se pasan a una declaración condicional.
Nota: Precaución: ¡No confundas los valores booleanos primitivos
verdadero
yfalso
con los valoresverdadero
yfalso
del objetoBooleano
!. Por ejemplo:
Ejemplo
En el siguiente ejemplo, la función comprobarDato
devuelve verdadero
si el número de caracteres del objeto Cadena
es igual a 3 (tres). De lo contrario, muestra una alerta y devuelve falso
.
Declaración elegir
Una instrucción elegir
permite que un programa evalúe una expresión e intente hacer coincidir el valor de la expresión con una etiqueta caso
. Si la encuentra, el programa ejecuta la declaración asociada.
Una instrucción elegir
se ve así:
elegir (expresion) {
caso etiqueta_1:
declaraciones_1
[romper;]
caso etiqueta_2:
declaraciones_2
[romper;]
…
porDefecto:
declaraciones_porDefecto
[romper;]
}
EsJS evalúa la instrucción elegir
anterior de la siguiente manera:
- El programa primero busca una cláusula
caso
con una etiqueta que coincida con el valor de expresión y luego transfiere el control a esa cláusula, ejecutando las declaraciones asociadas. - Si no se encuentra una etiqueta coincidente, el programa busca la cláusula opcional
porDefecto
:- Si se encuentra una cláusula
porDefecto
, el programa transfiere el control a esa cláusula, ejecutando las declaraciones asociadas. - Si no se encuentra una cláusula
porDefecto
, el programa reanuda la ejecución en la declaración que sigue al final deelegir
. - (Por convención, la cláusula
porDefecto
está escrita como la última cláusula, pero no es necesario que sea así).
- Si se encuentra una cláusula
Declaraciones romper
La declaración opcional romper
asociada con cada cláusula caso
asegura que el programa salga de elegir
una vez que se ejecuta la instrucción coincidente, y luego continúa la ejecución en la declaración que sigue a elegir
. Si se omite romper
, el programa continúa la ejecución dentro de la instrucción elegir
(y evaluará el siguiente caso
, y así sucesivamente).
Ejemplo
En el siguiente ejemplo, si tipoDeFruta
se evalúa como 'Bananas
', el programa hace coincidir el valor con el caso 'Bananas
' y ejecuta la declaración asociada. Cuando se encuentra romper
, el programa sale del elegir
y continúa la ejecución de la instrucción que sigue a elegir
. Si se omitiera romper
, también se ejecutará la instrucción para caso 'Cerezas'
.
Expresiones de manejo de excepciones
Puedes lanzar excepciones usando la instrucción lanzar
y manejarlas usando las declaraciones intentar...lanzar
.
Tipos de excepciones
Casi cualquier objeto se puede lanzar en EsJS. Sin embargo, no todos los objetos lanzados son iguales. Si bien es común lanzar números o cadenas como errores, con frecuencia es más efectivo usar uno de los tipos de excepción creados específicamente para este propósito:
- El más común:
Error
. - Otros siete tipos de
Error
.
Expresión lanzar
Utiliza la expresión lanzar
para lanzar una excepción. Una expresión lanzar
especifica el valor que se lanzará:
lanzar expresion;
Puedes lanzar cualquier expresión, no solo expresiones de un tipo específico. El siguiente código arroja varias excepciones de distintos tipos:
lanzar "Error2"; // tipo Cadena
lanzar 42; // tipo Numero
lanzar verdadero; // tipo Booleano
lanzar { // tipo Objeto
aCadena: funcion () {
retornar "¡Soy un objeto!";
},
};
lanzar Error('Error interno: código 1234'); // tipo Error
Nota: Puedes especificar un objeto cuando lanzas una excepción. A continuación, puedes hacer referencia a las propiedades del objeto en el bloque
capturar
.
Declaración intentar...lanzar
La declaración intentar...lanzar
marca un bloque de expresiones para probar y especifica una o más respuestas en caso de que se produzca una excepción. Si se lanza una excepción, la declaración intentar...lanzar
la detecta.
La declaración intentar...lanzar
consta de un bloque intentar
, que contiene una o más declaraciones, y un bloque capturar
, que contiene declaraciones que especifican qué hacer si se lanza una excepción en el bloque intentar
.
En otras palabras, deseas que el bloque intentar
tenga éxito, pero si no es así, deseas que el control pase al bloque capturar
. Si alguna instrucción dentro del bloque intentar
(o en una función llamada desde dentro del bloque intentar
) arroja una excepción, el control inmediatamente cambia al bloque capturar
. Si no se lanza ninguna excepción en el bloque intentar
, se omite el bloque capturar
. El bloque finalmente
se ejecuta después de que se ejecutan los bloques intentar
y capturar
, pero antes de las declaraciones que siguen a la declaración intentar...lanzar
.
Ejemplo
El siguiente ejemplo usa una instrucción intentar...lanzar
. El ejemplo llama a una función que recupera el nombre de un mes de un arreglo en función del valor pasado a la función. Si el valor no corresponde a un número de mes (1
-12
), se lanza una excepción con el valor "MesInvalido
" y pasan a ejecutarse las declaraciones del bloque capturar
. Puedes modificar el valor de la constante miMes
con un número inválido para experimentar este comportamiento.
El bloque capturar
Puedes usar un bloque capturar
para manejar todas las excepciones que se puedan generar en el bloque intentar
.
capturar (capturarID) {
instrucciones
}
El bloque capturar
especifica un identificador (capturarID
en la sintaxis anterior) que contiene el valor especificado por la expresión lanzar
. Puedes usar este identificador para obtener información sobre la excepción que se lanzó.
EsJS crea este identificador cuando se ingresa al bloque capturar
. El identificador dura solo la duración del bloque capturar
. Una vez que el bloque capturar
termina de ejecutarse, el identificador ya no existe.
Por ejemplo, el siguiente código lanza una excepción. Cuando ocurre la excepción, el control se transfiere al bloque capturar
.
intentar {
lanzar "miExcepcion"; // genera una excepción
} capturar (error) {
// declaraciones para manejar cualquier excepción
loguearMisErrores(error); // pasa el objeto exception al controlador de errorores
}
Nota: Mejores prácticas: Cuando se registran errores en la consola dentro de un bloque
capturar
, es conveniente utilizarconsola.error()
en lugar deconsola.escribir()
. Esto formatea el mensaje como un error y lo agrega a la lista de mensajes de error generados por la página.
El bloque finalmente
El bloque finalmente
contiene instrucciones que se ejecutarán después que se ejecuten los bloques intentar
y capturar
. Además, el bloque finalmente
ejecuta antes el código que sigue a la declaración intentar...capturar...finalmente
.
También es importante notar que el bloque finalmente
se ejecutará independientemente de que se produzca una excepción. Sin embargo, si se lanza una excepción, las declaraciones en el bloque finalmente
se ejecutan incluso si ningún bloque capturar
maneje la excepción que se lanzó.
Puedes usar el bloque finalmente
para hacer que tu script falle correctamente cuando ocurra una excepción. Por ejemplo, es posible que debas liberar un recurso que tu script haya inmovilizado.
El siguiente ejemplo abre un archivo y luego ejecuta declaraciones que usan el archivo. (EsJS de lado del servidor te permite acceder a los archivos). Si se lanza una excepción mientras el archivo está abierto, el bloque finalmente
cierra el archivo antes de que falle el script. Usar finalmente
aquí asegura que el archivo nunca se deje abierto, incluso si ocurre un error.
abrirMiArchivo();
intentar {
escribirMiArchivo(datos); // Esto puede arrojar un error
} capturar (e) {
controlarError(e); // Si ocurrió un error, manéjalo
} finalmente {
cerrarMiArchivo(); // Siempre cierra el recurso
}
Si el bloque finalmente
devuelve un valor, este valor se convierte en el valor de retorno de toda la producción de intentar...capturar...finalmente
, independientemente de las declaraciones retornar
en los bloques intentar
y capturar
:
La sobrescritura de los valores devueltos por el bloque finalmente
también se aplica a las excepciones lanzadas o relanzadas dentro del bloque capturar
:
Declaraciones intentar...lanzar
anidadas
Puedes anidar una o más declaraciones intentar...lanzar
.
Si un bloque intentar
interno no tiene un bloque capturar
correspondiente:
- debe contener un bloque
finalmente
, y - el bloque
capturar
adjunto de la declaraciónintentar...lanzar
se comprueba para una coincidencia.
Para obtener más información, consulta bloques try anidados
en la una página de referencia intentar...lanzar
.
Utilizar objetos Error
Dependiendo del tipo de error, es posible que puedas utilizar las propiedades nombre
y mensaje
para obtener un mensaje más refinado.
La propiedad nombre
proporciona la clase general de Error
(tal como DOMException
o Error
), mientras que mensaje
generalmente proporciona un mensaje más conciso que el que se obtendría al convertir el objeto error en una cadena.
Si estás lanzando tus propias excepciones, para aprovechar estas propiedades (por ejemplo, si tu bloque capturar
no discrimina entre tus propias excepciones y las del sistema), puedes usar el constructor Error
.
Por ejemplo: