|
| 1 | +# Nullish coalescing operator '??' |
| 2 | + |
| 3 | +[recent browser="new"] |
| 4 | + |
| 5 | +El _nullish coalescing operator_ `??` brinda una sintáxis corta para seleccionar la primera variable "definida" de una lista. |
| 6 | + |
| 7 | +El resultado de `a ?? b` es: |
| 8 | +- `a` si esta no es `null` o `undefined`, |
| 9 | +- `b`, en el caso contrario. |
| 10 | + |
| 11 | +Entonces, `x = a ?? b` es la versión corta de: |
| 12 | + |
| 13 | +```js |
| 14 | +x = (a !== null && a !== undefined) ? a : b; |
| 15 | +``` |
| 16 | + |
| 17 | +Aquí un ejemplo más detallado. |
| 18 | + |
| 19 | +Pensemos que tenemos un `firstName`, `lastName` o `nickName`, todos ellos opcionales. |
| 20 | + |
| 21 | +Escojamos el que esté definido y mostrémoslo (o mostremos "Anonymous" si ninguno está definido): |
| 22 | + |
| 23 | +```js run |
| 24 | +let firstName = null; |
| 25 | +let lastName = null; |
| 26 | +let nickName = "Supercoder"; |
| 27 | + |
| 28 | +// Muestra la primera variable que no sea null/undefined |
| 29 | +alert(firstName ?? lastName ?? nickName ?? "Anonymous"); // Supercoder |
| 30 | +``` |
| 31 | +
|
| 32 | +## Comparación con || |
| 33 | +
|
| 34 | +Esto es muy similiar al operador OR `||`. De hecho, podemos reemplazar `??` con `||` en el código anterior y obtener el mismo resultado. |
| 35 | +
|
| 36 | +La gran diferencia es que: |
| 37 | +- `||` retorna el primer valor _*truthy*_. |
| 38 | +- `??` retorna el primer valor _*defined*_. |
| 39 | +
|
| 40 | +Esto es de suma importancia cuando queremos tratar `null/undefined` diferente de `0`. |
| 41 | +
|
| 42 | +Por ejemplo: |
| 43 | +
|
| 44 | +```js |
| 45 | +height = height ?? 100; |
| 46 | +``` |
| 47 | +
|
| 48 | +Esto le asigna `100` a `height` si esta no está definida. En cambio si `height` es `0`, esta se mantiene "tal cual". |
| 49 | +
|
| 50 | +Comparémoslo con `||`: |
| 51 | +
|
| 52 | +```js run |
| 53 | +let height = 0; |
| 54 | + |
| 55 | +alert(height || 100); // 100 |
| 56 | +alert(height ?? 100); // 0 |
| 57 | +``` |
| 58 | +
|
| 59 | +En este caso, `height || 100` maneja `height` con un valor de `0` como no asignada, al igual que con `null`, `undefined` o cualquier otro valor _falsy_, dependiendo de la situación, esto puede ser incorrecto. |
| 60 | +
|
| 61 | +En el caso de `height ?? 100` este retorna `100` solo si `height` es exactamente `null` o `undefined`. |
| 62 | +
|
| 63 | +## Precedencia |
| 64 | +
|
| 65 | +La precedencia del operador `??` es bastante baja: `7` en la [Tabla MDN](https://developer.mozilla.org/es/docs/Web/JavaScript/Referencia/Operadores/Operator_Precedence#Table). |
| 66 | +
|
| 67 | +Es más baja que en la mayoría de los operadores y un poco más alta que `=` y `?`. |
| 68 | +
|
| 69 | +Así que si necesitas usar `??` en una expresión compleja, considera añadir paréntesis: |
| 70 | +
|
| 71 | +```js run |
| 72 | +let height = null; |
| 73 | +let width = null; |
| 74 | + |
| 75 | +// Importante: usar paréntesis |
| 76 | +let area = (height ?? 100) * (width ?? 50); |
| 77 | + |
| 78 | +alert(area); // 5000 |
| 79 | +``` |
| 80 | +
|
| 81 | +Caso contrario, si omitimos los paréntesis, entonces `*` tiene una mayor precedencia y se ejecutará primero. Eso sería lo mismo que: |
| 82 | +
|
| 83 | +```js |
| 84 | +// Incorrecto |
| 85 | +let area = height ?? (100 * width) ?? 50; |
| 86 | +``` |
| 87 | +
|
| 88 | +Existe también una limitación a nivel del lenguaje. Por razones de seguridad, está prohibido usar `??` junto con los operadores `&&` y `||`. |
| 89 | +
|
| 90 | +El siguiente código desencadena un error de sintáxis: |
| 91 | +
|
| 92 | +```js run |
| 93 | +let x = 1 && 2 ?? 3; // Syntax error |
| 94 | +``` |
| 95 | +
|
| 96 | +La limitación es sin duda alguna debatible, pero por ciertas razones fue agregada a la especificación del lenguaje. |
| 97 | +
|
| 98 | +Usa paréntesis explícitos para solucionarlo: |
| 99 | +
|
| 100 | +```js run |
| 101 | +let x = (1 && 2) ?? 3; // Funciona |
| 102 | +alert(x); // 2 |
| 103 | +``` |
| 104 | +
|
| 105 | +## Resumen |
| 106 | +
|
| 107 | +- El _nullish coalescing operator_ `??` proveé una manera concisa de seleccionar un valor "definido" de una lista. |
| 108 | +
|
| 109 | + Es usado para asignar valores por defecto a las variables: |
| 110 | +
|
| 111 | + ```js |
| 112 | + // Asignar height=100, si height es null o undefined |
| 113 | + height = height ?? 100; |
| 114 | + ``` |
| 115 | +
|
| 116 | +- El operador `??` tiene una precedencia muy baja, un poco más alta que `?` y `=`. |
| 117 | +- Está prohibido su uso con `||` y `&&` sin paréntesis explícitos. |
0 commit comments