Un valore predefinito più intelligente
JavaScript ha sempre avuto una scorciatoia per i valori predefiniti: value || fallback. Funziona quasi sempre, ma ha un difetto di fabbrica: considera "mancante" qualsiasi valore falsy. 0, '' e false fanno scattare tutti il ripiego, anche quando sono la risposta giusta.
L'operatore di nullish coalescing ?? risolve proprio questo. Ricorre al ripiego solo con null o undefined:
0 e '' sopravvivono. null e undefined no. Ecco tutto l'operatore.
Perché || non basta
Ecco il bug classico che ?? è nato per evitare:
L'utente ha chiesto volume 0 (silenzio) e un nickname vuoto. Entrambi i valori sono stati sovrascritti senza avviso, perché || non distingue tra "mancante" e "falsy".
Passa a ??:
Ora 0 e '' passano intatti, e solo i campi che mancano davvero ricevono il valore predefinito. È quasi sempre quello che vuoi.
Il modello mentale
?? si pone una sola domanda: il lato sinistro è null o undefined? Nient'altro conta.
| Valore a sinistra | sin || des restituisce | sin ?? des restituisce |
|---|---|---|
null | des | des |
undefined | des | des |
0 | des | sin (0) |
'' | des | sin ('') |
false | des | sin (false) |
NaN | des | sin (NaN) |
| qualsiasi oggetto | sin | sin |
Scegli ?? quando i tuoi dati contengono valori falsy con un significato. Scegli || quando vuoi davvero scartare tutto ciò che è falsy (stringhe vuote, contatori a zero e così via): quel caso esiste, ma è più raro di quanto si pensi.
Valutazione in cortocircuito
Come || e &&, anche ?? valuta in cortocircuito. Se il lato sinistro non è nullish, il lato destro non viene nemmeno eseguito:
expensiveDefault() viene eseguita una sola volta, per b. È utile quando il ripiego è una chiamata di funzione, una richiesta di rete o qualsiasi altra cosa che preferisci saltare quando non serve.
In coppia con l'optional chaining
?? e ?. sono stati introdotti insieme in ES2020 e sono pensati per lavorare in squadra. L'optional chaining percorre un cammino che potrebbe mancare e restituisce undefined se un passaggio non c'è; il nullish coalescing poi inserisce un valore predefinito sensato:
Senza questa coppia, lo stesso codice diventa una brutta catena di controlli && o un try/catch. Con loro, accesso sicuro e valori predefiniti sensati stanno in una riga.
Assegnazione nullish: ??=
a ??= b assegna b ad a solo quando a è null o undefined. È l'operatore di assegnazione logica nullish e valuta in cortocircuito: se a ha già un valore, il lato destro non viene valutato.
Nota che verbose: false e retries: 0 vengono conservati: ??= riempie solo ciò che manca davvero. Confrontalo con ||=, che li sovrascriverebbe entrambi.
Precedenza e la regola delle parentesi
?? si rifiuta di proposito di mescolarsi con || o && senza parentesi. Questo lancia un SyntaxError:
const x = a || b ?? c; // SyntaxError
Chi ha progettato il linguaggio ha ritenuto la precedenza abbastanza ambigua da obbligarti a chiarirla. Aggiungi le parentesi e tutto funziona:
Raggruppamenti diversi, risultati diversi. Le parentesi non sono decorative: dicono a chi leggerà il codice in futuro (e al parser) cosa intendevi.
Non è come un parametro predefinito
I parametri predefiniti nella firma di una funzione hanno una regola tutta loro: scattano solo quando l'argomento è undefined, non null. È una differenza sottile rispetto a ??, che tratta i due casi allo stesso modo.
Se vuoi che anche null faccia scattare il ripiego, usa ?? nel corpo della funzione:
Una piccola differenza, facile da trascurare quando un'API ti restituisce null per dire "nessun valore impostato".
Quando usare l'operatore ??
Usa ?? come operatore predefinito, a meno che tu non abbia un motivo preciso per non farlo. È quello che rispecchia meglio il comportamento reale dei dati: 0, '' e false di solito sono valori veri da conservare, e solo i dati davvero mancanti meritano un ripiego. Riserva || ai casi in cui vuoi davvero sostituire qualsiasi valore falsy.
Prossimo passo: le classi
Con questo chiudiamo il blocco su oggetti e array: hai gli strumenti per costruire e percorrere strutture di dati in sicurezza. Il prossimo capitolo passa all'organizzazione del comportamento: classi, ereditarietà e il sistema dei prototipi che c'è sotto.
Domande frequenti
Cos'è l'operatore di nullish coalescing in JavaScript?
?? restituisce l'operando di destra solo quando quello di sinistra è null o undefined. Negli altri casi restituisce il valore di sinistra invariato. L'espressione value ?? fallback è il modo standard per fornire un valore predefinito senza inciampare in valori falsy ma validi, come 0 o ''.
Qual è la differenza tra ?? e || in JavaScript?
|| ricorre al valore di ripiego con qualsiasi valore falsy: 0, '', false, NaN, null e undefined. ?? lo fa solo con null e undefined. Se nei tuoi dati 0 o una stringa vuota sono valori legittimi, usa ??. Se vuoi davvero scartare ogni valore falsy, || resta la scelta giusta.
Si può combinare ?? con l'optional chaining?
Sì, ed è un abbinamento molto comune. user?.settings?.theme ?? 'light' percorre la catena in modo sicuro, restituisce undefined se manca qualcosa lungo il percorso e poi applica 'light'. I due operatori sono arrivati insieme in ES2020 proprio per supportare questo schema.
Cosa fa l'operatore ??=?
a ??= b assegna b ad a solo se a vale null o undefined. È l'assegnazione logica nullish, una forma abbreviata di a = a ?? b, ma con cortocircuito: se a ha già un valore, la parte destra non viene nemmeno valutata. Utile per riempire i valori predefiniti mancanti in un oggetto di opzioni.