Menu

Operador ?? en JavaScript: valores por defecto bien hechos

Cómo el operador ?? elige un valor por defecto solo cuando algo es null o undefined, y por qué en la práctica le gana a ||.

Un valor por defecto más inteligente

JavaScript siempre ha tenido un atajo para asignar valores por defecto: value || fallback. Funciona casi siempre, pero arrastra un problema de fábrica: considera "ausente" cualquier valor falsy. Es decir, 0, '' y false disparan el fallback aunque sean la respuesta correcta.

El operador de nullish coalescing ?? viene a resolver justo eso. Solo recurre al valor por defecto cuando el original es null o undefined:

index.js
Output
Click Run to see the output here.

0 y '' sobreviven. null y undefined no. Ese es el operador entero.

Por qué || se queda corto

Este es el bug clásico que ?? vino a solucionar:

index.js
Output
Click Run to see the output here.

El usuario pidió volumen 0 (silencio) y un nick vacío. Los dos valores fueron pisados sin avisar porque || no distingue entre "no hay valor" y "valor falsy".

Cambia a ??:

index.js
Output
Click Run to see the output here.

Ahora el 0 y el '' pasan sin que nadie los toque, y solo los campos que realmente faltan acaban tomando el valor por defecto. Esto es, casi siempre, lo que buscas.

El modelo mental

?? se hace una única pregunta: ¿el operando de la izquierda es null o undefined? Ninguna otra cosa cuenta.

Valorizq || der devuelveizq ?? der devuelve
nullderder
undefinedderder
0derizq (0)
''derizq ('')
falsederizq (false)
NaNderizq (NaN)
cualquier objetoizqizq

Usa ?? cuando tus datos puedan tener valores falsy que sí significan algo. Usa || cuando de verdad quieras descartar todo lo falsy (cadenas vacías, contadores en cero, etc.) — ese caso existe, pero es menos habitual de lo que solemos pensar.

Evaluación en cortocircuito

Igual que || y &&, el operador ?? evalúa en cortocircuito. Si el operando de la izquierda no es nullish, el de la derecha ni siquiera se ejecuta:

index.js
Output
Click Run to see the output here.

expensiveDefault() se ejecuta una sola vez: solo para b. Esto resulta muy útil cuando tu valor por defecto es una llamada a función, una petición de red o cualquier otra operación que prefieres evitar si no hace falta.

Combinando con optional chaining

Los operadores ?? y ?. aparecieron juntos en ES2020 y están pensados para trabajar en equipo. El optional chaining recorre una ruta que podría no existir y devuelve undefined si alguno de los pasos falta; después, el nullish coalescing se encarga de poner un valor por defecto razonable:

index.js
Output
Click Run to see the output here.

Sin esta pareja, el mismo código se convierte en una cadena fea de && o en un try/catch. Con ellos, el acceso seguro y los valores por defecto caben en una sola línea.

Asignación nullish: ??=

a ??= b asigna b a a solo cuando a es null o undefined. Es el operador de asignación lógica nullish, y usa evaluación en cortocircuito: si a ya tiene un valor, la expresión de la derecha ni siquiera se evalúa.

index.js
Output
Click Run to see the output here.

Fíjate en que verbose: false y retries: 0 se conservan: ??= solo rellena lo que realmente falta. Compáralo con ||=, que pisaría ambos valores.

Precedencia y la regla de los paréntesis

El operador ?? se niega a propósito a mezclarse con || o && sin paréntesis. Esto lanza un SyntaxError:

const x = a || b ?? c;   // SyntaxError

Quienes diseñaron el lenguaje consideraron que la precedencia era lo bastante ambigua como para obligarte a dejarlo claro. Basta con añadir paréntesis y listo:

index.js
Output
Click Run to see the output here.

Agrupaciones distintas, resultados distintos. Los paréntesis no son decorativos: le están diciendo a quien lea tu código mañana (y al parser) qué era lo que querías expresar.

No es lo mismo que un parámetro por defecto

Los parámetros por defecto en la firma de una función tienen su propia lógica: solo se activan cuando el argumento es undefined, nunca cuando es null. Ahí está la diferencia sutil con ??, que trata ambos casos por igual.

index.js
Output
Click Run to see the output here.

Si también quieres que null dispare el valor por defecto, usa ?? dentro del cuerpo:

index.js
Output
Click Run to see the output here.

Pequeña diferencia, pero fácil de pasar por alto cuando una API te devuelve null para indicar "sin valor".

¿Cuándo usar el operador ?? en JavaScript?

Toma ?? como tu operador por defecto, salvo que tengas un motivo concreto para no hacerlo. Es el que mejor encaja con el comportamiento real de los datos: 0, '' y false suelen ser valores legítimos que conviene conservar, y solo los datos realmente ausentes (null o undefined) merecen un valor por defecto. Deja || para esos casos puntuales en los que sí quieres reemplazar cualquier valor falsy.

Siguiente paso: clases

Con esto cerramos el bloque de objetos y arrays: ya tienes las herramientas para construir y recorrer estructuras de datos sin llevarte sustos. En el próximo capítulo damos el salto a organizar el comportamiento: clases, herencia y el sistema de prototipos que hay por debajo.

Preguntas frecuentes

¿Qué es el operador de nullish coalescing en JavaScript?

?? devuelve el operando de la derecha únicamente cuando el de la izquierda es null o undefined. En cualquier otro caso, deja pasar el valor original. La expresión value ?? fallback es la forma estándar de asignar un valor por defecto sin tropezar con valores falsy que sí son válidos, como 0 o ''.

¿Cuál es la diferencia entre ?? y || en JavaScript?

|| recurre al fallback con cualquier valor falsy: 0, '', false, NaN, null y undefined. ?? solo lo hace con null y undefined. Si en tus datos 0 o una cadena vacía son valores legítimos, usa ??. Si lo que realmente quieres es descartar cualquier valor falsy, || sigue siendo la opción correcta.

¿Se puede combinar ?? con optional chaining?

Sí, de hecho es una de las combinaciones más habituales. user?.settings?.theme ?? 'light' recorre la cadena de forma segura, devuelve undefined si algo falta por el camino y entonces aplica 'light'. Ambos operadores llegaron juntos en ES2020 precisamente para cubrir este patrón.

¿Qué hace el operador ??=?

a ??= b asigna b a a solo si a vale null o undefined. Es la asignación lógica nullish, una forma corta de a = a ?? b, pero con cortocircuito: si a ya tiene valor, ni siquiera se evalúa la parte derecha. Muy útil para rellenar defaults que faltan en un objeto de opciones.

Aprende a programar con Coddy

COMENZAR