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
anon è 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 || 100controlla seheightha un valore falso: così è.- il risultato è dunque il secondo argomento,
100.
- il risultato è dunque il secondo argomento,
height ?? 100controlla 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…)