Características de Operadores
Si bien conocemos el comportamiento de los operadores aritméticos, de asignación y de comparación, existen otros operadores que nos permiten realizar operaciones más complejas.
JavaScript cuenta con una gran cantidad de operadores y mecanismos que nos permiten simplificar la escritura de código y realizar operaciones más avanzadas. En este apartado, veremos algunos detalles sobre el uso y funcionamiento de estas características.
Cortocircuito
El intéprete de JavaScript evalúa las expresiones lógicas de izquierda a derecha, lo cual permite que se detenga la evaluación de la expresión si el resultado ya es conocido.
Este comportamiento se conoce como evaluación de cortocircuito (short-circuit evaluation), y es muy útil para simplificar la escritura de código y evitar errores.
La expresión lógica AND (&&) es un operador de cortocircuito en el cual todos los operandos son convertidos a valores booleanos. Si el resultado de una conversión es false, el operador AND detiene la evaluación y devuelve el valor original que causó la conversión a false.
1<expresión falsa> && <expresión>La <expresión> nunca es evaluada porque el primer operando es false. Si la <expresión> es una función, esta nunca es invocada.
La expresión lógica OR (||) es un operador de cortocircuito en el cual todos los operandos son convertidos a valores booleanos. Si el resultado de una conversión es true, el operador OR detiene la evaluación y devuelve el valor original que causó la conversión a true.
1<expresión verdadera> || <expresión>La <expresión> nunca es evaluada porque el primer operando es true. Si la <expresión> es una función, esta nunca es invocada.
El operador (??) es un operador de cortocircuito conocido como fusión nula (nullish coalescing). Este operador devuelve el valor del operando derecho si el operando izquierdo es null o undefined, de lo contrario, devuelve el valor del operando izquierdo.
1<expresión izquierda> ?? <expresión derecha>Este operador puede interpretarse como un caso particular del operador OR (||), el cual devuelve el valor del operando derecho si el operando izquierdo es un valor falso, como '' o 0. En este caso, el operador ?? esta condicionado a null o undefined.
1let or_operation = "" || "valor verdadero"; // 'valor verdadero'2console.log(or_operation);3
4let nullish_operation = null ?? "valor verdadero"; // 'valor verdadero'5console.log(nullish_operation);6
7nullish_operation = undefined ?? "valor verdadero"; // 'valor verdadero'8console.log(nullish_operation);Evidentemente, si ninguno de los operandos es null o undefined, el operador ?? devuelve el valor del operando izquierdo.
1let nullish_operation = "operando izquierdo" ?? "operando derecho"; // 'operando izquierdo'2console.log(nullish_operation);Operador ternario
El operador ternario (?:) es un operador condicional que permite evaluar una expresión y devolver un valor en función de si la expresión es verdadera o falsa.
La sintaxis del operador ternario es la siguiente:
1<expresión> ? <valor si verdadero> : <valor si falso>Este operador abstrae el flujo de control de una sentencia if-else en una sola línea, lo cual permite simplificar la escritura de código.
1let valor = 10;2
3let mensaje =4 valor > 05 ? "El valor es positivo"6 : "El valor es negativo o cero";7console.log(mensaje);La estructura if-else equivalente al operador ternario del ejemplo anterior sería la siguiente:
1let valor = 10;2
3let mensaje;4if (valor > 0) {5 mensaje = "El valor es positivo";6} else {7 mensaje = "El valor es negativo o cero";8}9console.log(mensaje);Por supuesto, el operador ternario puede ser anidado para evaluar múltiples condiciones.
La sintaxis del operador ternario anidado es la siguiente:
1<expresión> ? <valor si verdadero> : <expresión> ? <valor si verdadero> : <valor si falso>Este operador permite evaluar múltiples condiciones en una sola línea, lo cual puede simplificar la escritura de código.
1let valor = 10;2
3let mensaje =4 valor > 05 ? "El valor es positivo"6 : valor < 07 ? "El valor es negativo"8 : "El valor es cero";9console.log(mensaje);La estructura if-else equivalente al operador ternario anidado del ejemplo anterior sería la siguiente:
1let valor = 10;2
3let mensaje;4if (valor > 0) {5 mensaje = "El valor es positivo";6} else if (valor < 0) {7 mensaje = "El valor es negativo";8} else {9 mensaje = "El valor es cero";10}11console.log(mensaje);Operador de propagación
La sintaxis extendida (spread syntax) es un mecansimo que permite a un elemento iterable, como un arreglo o un objeto, ser expandido en lugares donde cero o más argumentos (para llamadas de función) o elementos (para arreglos literales) son esperados. Para esto se emplea el operador de propagación (...) como prefijo del elemento iterable.
1let arreglo = [1, 2, 3];2
3let nuevo_arreglo = [0, ...arreglo, 4, 5];4console.log(nuevo_arreglo); // [0, 1, 2, 3, 4, 5]En este caso, el operador de propagación ... permite expandir los elementos del arreglo arreglo en el nuevo arreglo nuevo_arreglo.
1let objeto = { a: 1, b: 2 };2
3let nuevo_objeto = { ...objeto, c: 3, d: 4 };4console.log(nuevo_objeto); // { a: 1, b: 2, c: 3, d: 4 }En este caso, el operador de propagación ... permite expandir las propiedades del objeto objeto en el nuevo objeto nuevo_objeto.
1let arreglo = ["Python", "Java", "C++", "JavaScript"];2
3function mostrar(...lenguajes) {4 for (let i = 0; i < lenguajes.length; i++) {5 console.log("Lenguaje:", lenguajes[i]);6 }7}8
9mostrar(...arreglo);En este caso, el operador de propagación ... permite expandir los elementos del arreglo arreglo en los argumentos de la función mostrar.
También es posible utilizar el operador de propagación en la asignación de arreglos, donde podremos desestructurar el arreglo en variables individuales.
1let arreglo = ["Python", "Java", "C++", "JavaScript"];2
3let [primer_elemento, ...resto_elementos] = arreglo;4console.log(primer_elemento); // 'Python'5console.log(resto_elementos); // ['Java', 'C++']