El operador ternario es un condicional simple que ejecuta una de dos instrucciones posibles dependiendo de la evaluación previa de una condición.
Su sintaxis es la siguiente:
condition ? instructionIfTrue : instructionIfFalse; |
Donde:
– condition es una expresión de tipo Booleana.
– instructionIfTrue es la expresión que se ejecuta si condition es igual a true.
– instructionIfFalse es la expresión que se ejecuta si condition es igual a false.
Su uso suele asociarse a la asignación del valor para una variable que depende de alguna condición:
var status = ( user.name && user.pass ) ? 'Logged' : 'Unlogged'; |
Básicamente, se trata de una forma abreviada de una instrucción if … else.
Estructura larga del operador ternario
Si nos encontramos cómodos utilizando este operador, podemos ir más allá de su definición y crear estructuras largas que ejecuten varias acciones distintas dependiendo de una serie de condiciones.
Revisemos el siguiente código:
var a = 11; var numberLiteral = a == 5 ? 'Five' : a == 7 ? 'Seven' : a == 11 ? 'Eleven' : a == 15 ? 'Fifteen' : 'Other Number'; console.log( numberLiteral ); // Eleven |
Con esta estructura establecemos una serie de valores según el resultado del condicional como si fuera una clásica estructura if … else u otra de tipo switch. El resultado es un bloque muy legible y sencillo de mantener.
Si medimos el rendimiento de cada una de estas posibilidades, obtendremos la siguiente tabla:
Los datos son, como siempre, interesantes:
– En Chrome, el método más rápido es el switch.
– En Firefox 4, el ternario y el if…else andan parejos, pero el switch es 15 veces más lento!
– En Internet Explorer, todos los métodos tienen un rendimiento similar: bajo.
– En Opera, el ternario es ligeramente más lento, pero todos mantienen un buen rendimiento.
El test puede consultarse de forma online aquí.
Jugando con el operador ternario
Para las asignaciones booleanas de tipo true – false, podemos emular la estructura ternaria con la asignación por igualdad. Por ejemplo, el siguiente código
var language = 'Javascript'; var dynamic = ( language === "Javascript" ) ? true : false; console.log( dynamic ); // true |
puede reescribirse como:
var language = 'Javascript'; var dynamic = language === 'Javascript'; console.log( dynamic ); // true |
Curiosamente, si medimos el rendimiento de ambas estructuras encontramos que, según el navegador testeado, una puede ser más rápida que otra pero siempre se mantienen muy cerca.
Podemos ver el análisis comparativo realizado en JSPerf aquí.
Conclusión
El operador ternario es una estructura condicional muy interesante que permite ahorrarnos unos cuantos caracteres a la hora de asignar un determinado valor según una condición previa.
El test de rendimiento nos demuestra que se defiende dignamente frente a otras estructuras como son los bloques if…else o switch. Su elección dependerá finalmente de nuestro propio criterio y de lo cómodos que nos encontremos frente a su uso.
Yo realmente soy fan de este operador, simplifica mucho el código y lo hace bastante más legible.
Como curiosidad para los que lo utilicen, hay que tener en cuenta que en PHP el operador ternario tiene asociatividad por la izquierda, al contrario que en JavaScript o en C. Es decir, si cogemos ese mismo ejemplo y lo pasamos a PHP:
El resultado que obtendremos no es «Eleven» como esperamos, sino «Fifteen». ¿Por qué? Pues porque el código que se está ejecutando en realidad es este:
Si quisiéramos obtener el mismo resultado que espreamos en JavaScript, habría que reescribir el código de la siguiente manera:
Un saludo 🙂
Gran aporte Josep!
Es interesante comprobar como cada lenguaje implementa sus funcionalidades de manera distinta. Lástima que en PHP, con tanto paréntesis, se pierda parte de la legibilidad de esta estructura en Javascript.
PD: Corregido el literal en el ejemplo 🙂
Un saludo!
Cuando necesitaba hacer múltiples comparaciones, recurría precisamente a «switch», aunque uso con mucha frecuencia el operador ternario. Qué bueno saber que existe otra alternativa igual de simple basado en ese operador.
Una de las operaciones más comunes cuando se trabaja con datos de entrada es el uso del operador «ifsetor», es usado para proporcionar un valor por defecto cuando una entrada no existe o no es valida.
Lo habitual en estos casos es ver algo como esto:
Aplicando la sintaxis ifsetor, podemos simplificar la condición ternaria:
El ifsetor es un comando que funciona bien en PHP pero que no está implementado en el estándar Javascript.
En este lenguaje, lo arreglaríamos con la asignación por igualdad booleana:
El resultado es similar, solo que hay que tener en cuenta que se estarían evaluando también los falsy values.
Gracias Pasku!
Yo confesaré que siempre que puedo, utilizo un array de índices para este tipo de cosas:
no creo que el caso expuesto funcione, ya que el índice es un String y la variable contiene un número, pero va bien para hacerse una idea
😉
Es una solución que yo también utilizo a menudo.
La única pega es que es algo más lenta que la propuesta con el operador ternario. No es muy significativa pero cuando se trata de medir hasta el último milisegundo, hay que tenerlo en cuenta.
Gracias por el aporte Mekkon!
Pues sí, es más lenta, realmente se tienen que probar estas cosas, si no nunca se sabe
como curiosidad, en ubuntu con firefox 3.6.13 apenas hay diferencias en cuanto a velocidad entre los tres tests, el ternario sigue siendo el más rápido de todas formas 😉
Hay algo que no sé si es un typo o es que no lo he entendido: ¿dices que estas dos expresiones son equivalentes?
var language = ‘Javascript’;
var dynamic = ( language === «Javascript» ) ? true : false;
console.log( dynamic ); // true
y:
var language = ‘Javascript’;
var dynamic = language == ‘Javascript’;
console.log( dynamic ); // true
¿Por qué una con == y la otra con ===?
Si: efectivamente es un typo. Para guardar la integridad, debería usarse siempre el comparador estricto «===».
Gracias por el aviso!
El switch más rápido en chrome?
Vaya, que le pasara a php con esa estructura