Il nullish coalescing operator è rappresentato da due punti di domanda ??
.
Siccome trattiamo null
e undefined
in modo simile, avremo bisogno di una definizione particolare. In questo articolo, diremo che un’espressione è “definita” quando non è né null
né undefined
.
Il risultato di a ?? b
è:
- se
a
è definito, alloraa
, - se
a
non è definito, allorab
.
In altre parole, tra due operatori ??
ritorna il primo se questo non è null/undefined
; altrimenti, ritorna il secondo.
Il nullish coalescing operator non è qualcosa di completamente nuovo. È solo un modo più elegante per recuperare il primo valore “definito” tra due operatori.
Possiamo riscrivere result = a ?? b
usando gli operatori che già conosciamo, nel seguente modo:
result = (a !== null && a !== undefined) ? a : b;
Un caso d’uso comune per l’operatore ??
è quello di fornire un valore di default per una variabile potenzialmente “non definita”.
Per esempio, qui mostriamo Anonymous
se user
non è definito:
let user;
alert(user ?? "Anonymous"); // Anonymous (user not defined)
Ovviamente, se user
ha un qualsiasi valore eccetto null/undefined
, allora vedremo quel valore:
let user = "John";
alert(user ?? "Anonymous"); // John (user defined)
Possiamo anche usare una sequenza di ??
per selezionare, da una lista, il primo valore che non sia null/undefined
.
Per esempio, supponiamo di avere i dati di un utente nelle variabili firstName
, lastName
o nickName
. Tutte queste potrebbero essere non definite, se l’utente dovesse decidere di non inserirne i valori.
Vorremmo visualizzare il nome dell’utente usando una di queste variabili, oppure mostrare “Anonymous” se nessuna di esse è definita.
Usiamo l’operatore ??
:
let firstName = null;
let lastName = null;
let nickName = "Supercoder";
// mostra il primo valore valido:
alert(firstName ?? lastName ?? nickName ?? "Anonymous"); // Supercoder
Confronti con ||
L’operatore OR ||
può essere usato nello stesso modo dell’operatore ??
, come descritto nel capitolo precedente.
Per esempio, nel codice precedente potremmo rimpiazzare ??
con ||
e ottenere comunque il medesimo risultato:
let firstName = null;
let lastName = null;
let nickName = "Supercoder";
// mostra il primo valore vero:
alert(firstName || lastName || nickName || "Anonymous"); // Supercoder
L’operatore OR ||
esiste sin dagli inizi di JavaScript e gli sviluppatori lo hanno usato a tale scopo per molto tempo.
Il nullish coalescing operator ??
, invece, è stato aggiunto recentemente. La ragione è che alcuni sviluppatori non erano del tutto contenti dell’operatore ||
.
L’importante differenza tra essi è la seguente:
||
ritorna il primo valore truthy.??
ritorna il primo valore definito.
In altre parole, ||
non distingue tra false
, 0
, una stringa vuota ""
e null/undefined
. In contesto booleano sono tutti valori false
. Se uno di questi è il primo argomento di ||
, verrà ritornato il secondo argomento.
In pratica, però, potremmo voler usare il valore di default solamente quando la variabile è null/undefined
. Ovvero quando è veramente non definita: una stringa vuota ''
o 0
, ad esempio, potrebbero tornarci utili.
Per esempio, consideriamo il seguente codice:
let height = 0;
alert(height || 100); // 100
alert(height ?? 100); // 0
height || 100
controlla seheight
ha un valore falso: così è.- il risultato è dunque il secondo argomento,
100
.
- il risultato è dunque il secondo argomento,
height ?? 100
controlla seheight
ènull/undefined
: non lo è.- quindi il risultato è
height
, ovvero0
.
- quindi il risultato è
Se un’altezza pari a zero è un valore accettabile, questo non dovrebbe essere rimpiazzato con il valore di default (il secondo operatore, nel’esempio sopra 100
); in questo caso il nullish coalescing operator ??
è la scelta giusta.
Precedenza
La precedenza dell’operatore ??
è piuttosto bassa: 5
nella MDN table. Quindi ??
è valutato prima di =
e ?
, ma dopo la maggior parte degli altri operatori, come +
o *
.
Quindi, se volessimo scegliere un valore tramite l’operatore ??
in un’espressione contenente altri operatori, dovremmo considerare l’utilizzo delle parentesi:
let height = null;
let width = null;
// importante: utilizzare le parentesi
let area = (height ?? 100) * (width ?? 50);
alert(area); // 5000
Altrimenti, se omettessimo le parentesi, siccome *
ha una precedenza maggiore rispetto a ??
, sarebbe eseguito prima, portando a risultati scorretti.
// senza parentesi
let area = height ?? 100 * width ?? 50;
// ...funziona allo stesso modo del seguente codice (probabilmente non ciò che vogliamo)
let area = height ?? (100 * width) ?? 50;
Usare ?? con && o ||
Per motivi di sicurezza, JavaScript proibisce l’utilizzo di ??
insieme agli operatori &&
e ||
, a meno che la precedenza non sia esplicitamente specificata tramite l’utilizzo delle parentesi.
Il codice sotto causa un errore di sintassi:
let x = 1 && 2 ?? 3; // Syntax error
La limitazione è sicuramente discutibile, ma fu aggiunta alle specifiche del linguaggio‑quando le persone hanno iniziato ad utilizzare ??
al posto di ||
- con lo scopo di evitare errori di programmazione.
Per aggirare il problema si possono utilizzare delle parentesi esplicite:
let x = (1 && 2) ?? 3; // Works
alert(x); // 2
Riepilogo
-
Il nullish coalescing operator
??
fornisce una scorciatoia per la scelta del primo valore “definito” da una lista di valori.È usato per assegnare valori di default alle variabili:
// imposta height = 100 se 'height' è *null* o *undefined* height = height ?? 100;
-
L’operatore
??
ha una precedenza molto bassa, solo un po’ più alta di?
e=
, quindi va considerata l’aggiunta di parentesi quando lo si utilizza all’interno di un’espressione. -
È proibito usarlo con
||
o&&
senza l’utilizzo di parentesi esplicite.
Commenti
<code>
, per molte righe – includile nel tag<pre>
, per più di 10 righe – utilizza una sandbox (plnkr, jsbin, codepen…)