Parametri vs argomenti
Due parole che si confondono di continuo. Un parametro è il nome nella definizione della funzione. Un argomento è il valore che passi quando la chiami. È la stessa idea di Python e della maggior parte degli altri linguaggi:
a e b sono parametri. 2 e 3 sono argomenti. JavaScript li associa per posizione: il primo argomento al primo parametro, e così via. La differenza è piccola, ma è il vocabolario usato dai messaggi di errore e da MDN.
JavaScript è permissivo sul numero di argomenti
A differenza di molti linguaggi, a JavaScript non importa se passi troppi o troppo pochi argomenti. I parametri mancanti diventano undefined. Quelli in più vengono ignorati in silenzio:
La prima chiamata stampa Hello, Ada undefined: last non ha ricevuto alcun valore, quindi è undefined, e i template literal lo interpolano senza problemi. Nessun errore, nessun avviso. Questa tolleranza a volte è utile e a volte è fonte di bug, ed è proprio per questo che esistono i parametri predefiniti.
Impostare un valore predefinito
Metti = e un valore dopo il nome del parametro. Se chi chiama non passa quell'argomento (o passa undefined), entra in gioco il default:
Tutte e tre le chiamate funzionano. La prima e la terza attivano il default; la seconda usa il valore passato. È sintassi ES6: prima del 2015 dovevi scrivere name = name || "friend" dentro il corpo, che aveva i suoi bug con valori falsy come 0 e "".
I valori predefiniti possono essere qualsiasi espressione, non solo letterali:
L'espressione viene valutata a ogni chiamata, non una volta sola quando la funzione è definita. Quindi niente trappola dei default mutabili come in Python: ogni chiamata riceve un new Date() nuovo.
Solo undefined attiva il default
Questa è la regola che sorprende molti. I default scattano quando l'argomento è undefined, non quando è falsy, e nemmeno quando è null:
Solo l'ultima chiamata usa "friend". Passare null in modo esplicito significa dire "il valore è null", e JavaScript ti prende in parola. Lo stesso vale per stringhe vuote e zeri: sono valori, non argomenti mancanti.
Se vuoi trattare null come un argomento mancante, devi gestirlo tu:
L'operatore ?? (nullish coalescing) tratta sia null sia undefined come "mancante". Lo vedremo meglio in un capitolo successivo.
I default possono usare i parametri precedenti
I parametri vengono valutati da sinistra a destra, quindi un default successivo può usare qualsiasi parametro venga prima:
Una chiamata con un solo argomento produce un cubo. Con due argomenti ottieni un prisma a base quadrata. La direzione conta: non puoi fare riferimento a un parametro non ancora dichiarato:
function bad(a = b, b = 1) {
return a + b;
}
bad(); // ReferenceError: Cannot access 'b' before initialization
Stesse regole delle variabili dichiarate con let: usarle prima di dichiararle è un errore.
I default e la destrutturazione
Puoi destrutturare i parametri e assegnare dei default nello stesso momento. È un pattern comune per gli argomenti di tipo "oggetto di opzioni":
Qui lavorano due livelli di default. Quelli interni (role = "member", active = true) riempiono le proprietà mancanti. Quello esterno = {} gestisce il caso in cui chi chiama non passa alcun argomento: senza, createUser() proverebbe a destrutturare undefined e lancerebbe un errore.
All'inizio il pattern sembra denso, ma è ovunque nelle codebase JavaScript moderne. Quando il tuo occhio riconosce { ... } = {} come "opzioni con default", si legge al volo.
Saltare un argomento intermedio
JavaScript non ha argomenti con nome come Python. Per saltare un parametro intermedio e usarne il default, devi passare undefined in modo esplicito:
Passare undefined per prefix mantiene il default. È brutto da vedere. Se ti ritrovi spesso a scrivere undefined nelle chiamate, è il segnale che conviene passare a un oggetto di opzioni:
Ora chi chiama indica per nome cosa vuole sovrascrivere, e l'ordine non conta.
I default non contano in length
Un piccolo dettaglio che conta di rado ma a volte confonde. La proprietà length di una funzione riporta il numero di parametri prima del primo che ha un default:
Le librerie che ispezionano le funzioni (come alcuni strumenti di test e di dependency injection) usano length per contare i parametri "obbligatori". Utile sapere che la regola esiste; non vale la pena memorizzarla a meno che tu non stia scrivendo strumenti del genere.
Prossimo passo: rest e spread
I default gestiscono il caso in cui conosci i parametri in anticipo. A volte non li conosci: vuoi che una funzione accetti un numero qualsiasi di argomenti, o inoltrare un gruppo di argomenti a un'altra funzione. È a questo che servono ...rest e l'operatore spread, nella prossima pagina.
Domande frequenti
Come si imposta un valore predefinito per un parametro in JavaScript?
Metti = e il valore predefinito subito dopo il nome del parametro nella firma della funzione: function greet(name = 'friend') { ... }. Se chi chiama non passa nessun valore (o passa undefined), viene usato il valore predefinito. È sintassi ES6 e funziona in tutti gli ambienti JavaScript moderni.
Che differenza c'è tra parametri e argomenti?
I parametri sono i nomi nella definizione della funzione: function add(a, b) ha i parametri a e b. Gli argomenti sono i valori reali passati quando la chiami: add(2, 3) passa gli argomenti 2 e 3. La distinzione conta quando leggi messaggi di errore e documentazione.
Il parametro predefinito scatta se passo null?
No. I valori predefiniti scattano solo quando l'argomento è undefined (o manca del tutto). Passare null in modo esplicito significa "ti sto dando un valore, e il valore è null", quindi il default viene saltato. Questo sorprende chi arriva da linguaggi in cui null e undefined sono la stessa cosa.
Un valore predefinito può fare riferimento a un altro parametro?
Sì. I parametri vengono valutati da sinistra a destra, quindi il default di un parametro successivo può usare quelli precedenti: function box(width, height = width). Puoi anche chiamare funzioni nel default, per esempio function log(msg, time = Date.now()), e l'espressione viene rieseguita a ogni chiamata.