Codeando en JS muchas veces nos encontramos con objetos que no siempre tienen el formato que nosotros esperamos, lo que nos obliga a checkear por undefined en cada paso con el que nos adentramos al mismo, rápidamente vemos como nuestro código crece solamente con estas validaciones, para ayudarnos con esto llegan en ES2020 el optional chaining y el nullish coalescing.
Para comprender realmente la utilidad de estos operadores vamos a usar el siguiente ejemplo:
Supongamos que estamos desarrollando una aplicación que necesita usar un servicio que nos devuelve objetos describiendo usuarios de un foro con el siguiente formato:
let usuario = {
nombre: "Mario",
contacto: {
mail: "",
telefono: {
fijo: 47221612,
movil: 1148162033
},
},
puedeCrearNuevosPosteos: true
}
Sin embargo sabemos que hay datos, el contacto por ejemplo, que son opcionales al momento de crear la cuenta de usuario, y no solo eso, también nos damos cuenta que a veces este servicio devuelve usuarios con propiedades faltantes.
Optional Chaining operator
Este operador agregado en ES2020 nos permite obtener valores profundamente anidados en objetos sin tener que hacer validaciones en cada uno de sus niveles.
Supongamos que queremos obtener el número de celular de uno de los usuarios, pero como dijimos, al momento de crear una nueva cuenta de usuario es opcional ingresar un contacto, entonces si quisieramos obtener este dato, lo buscaríamos de alguna de las siguientes formas:
if(usuario.contacto && usuario.contacto.telefono) {
return usuario.contacto.telefono.movil;
}
//Esto es equivalente a:
return usuario.contacto && usuario.contacto.telefono && usuario.contacto.telefono.movil;
Vemos que la mayoría del código que escribimos es para validaciones, y no para obtener el número de celular, que es lo que queríamos. Esto lo solucionamos con optional chaining, se usa simplemente agregando un signo de pregunta luego de cada propiedad que sabemos que podría no estar
return usuario.contacto?.telefono?.movil;
En el caso de no existir contacto o teléfono, esta sentencia devolverá undefined, y en el caso contrario nos devolvería el valor de movil, ahorrandonos asi varias líneas de código.
Nullish coalescing
Ahora supongamos que necesitamos saber si un usuario puede crear posteos, sabemos que esta es una funcionalidad nueva y que no se le agregó la propiedad "puedeCrearNuevosPosteos" a los usuarios viejos, por lo tanto al evaluarla nos devolverá false, tanto cuando el usuario no tenga la propiedad como cuando realmente sea false, haciendo que los usuarios viejos no puedan postear. Esto es porque JavaScript cuenta con varios valores "falsy", es decir, valores que de ser evaluados en una condición nos darían false, estos son undefined, null, false, 0, NaN y "", un string vacío. Normalmente para hacer que los usuarios viejos puedan postear haríamos lo siguiente:
return usuario.puedeCrearNuevosPosteos == undefined ||
usuario.puedeCrearNuevosPosteos == null ||
usuario.puedeCrearNuevosPosteos;
Tenemos el mismo problema que en el ejemplo anterior, mas código para evitar casos indeseados que para lograr la funcionalidad pedida. Usando nullish coalescing podremos distinguir facilmente entre variables con un valor de verdad falso y variables sin declarar o con valor null. Nos es útil, para distinguir entre usuarios que no pueden crear nuevos posteos y usuarios que simplemente no tienen la propiedad definida. Se usa simplemente agregando dos signos de interrogación después de la propiedad que creemos pueda ser undefined o null.
return usuario.puedeCrearNuevosPosteos ?? true;
Esto nos devolvería el valor buscado a menos que sea null o undefined, en tal caso nos devolvería true. Explicado brevemente, si lo que hay a la izquierda del operador ?? es distinto a null o undefined, devuelve su valor, de lo contrario devuelve lo que pongamos a su derecha.