Per quanto questo articolo sia ancora validissimo, consiglio di leggere anche il nuovo articolo sulle funzioni JavaScript che fa parte del corso gratuito a tema.
Arrivati a questo punto del nostro percorso abbiamo già visto e parlato delle funzioni, soprattutto nell'articolo relativo allo scope delle variabili, ma non abbiamo mai approfondito come si deve il concetto. Bene, in questo articolo lo faremo.
Cos'è una funzione?
Le funzioni sono un concetto fondamentale della programmazione. Ogni linguaggio di programmazione di alto livello mette a disposizione del programmatore la possibilità di creare e di usare funzioni.
Nello specifico le funzioni sono un insieme di istruzioni che eseguono un compito. Le funzioni potrebbero richiedere degli input per restituire un output (la somma necessita degli addendi per poter restituire il risultato).
Personalmente mi piace correlare le funzioni alle ricette di cucina. Una ricetta non è altro che una serie di passaggi (istruzioni) che alla fine producono un risultato (output). Le ricette per poter restituire un output necessitano degli ingredienti (input).
Semplice se lo mettiamo in questi termini, no?
Definire una funzione
La definizione di una funzione consiste nell'usare la parola chiave function
, seguita da:
- Il nome della funzione
- Una lista di parametri racchiusi tra parentesi tonde e separati da virgole
- La serie di istruzioni racchiuse tra parentesi graffe
{...}
Ecco un esempio:
1function somma(addendo1, addendo2) {
2 return addendo1 + addendo2;
3}
La funzione somma
prende due parametri, chiamati addendo1
e addendo2
. La funzione restituirà un valore (la somma dei due parametri). La parola chiave return
termina l'esecuzione della funzione e restituisce alla parte di programma che ha chiamato la funzione il valore calcolato.
Chiamare una funzione
Per "parte di programma che ha chiamato la funzione" si intende quella riga di codice dove il programmatore ha scritto:
1somma(5, 2);
La parola chiave function
serve solo in fase di dichiarazione e non bisogna ripeterla ogni volta che la funzione viene chiamata, anche perché altrimenti JavaScript vi cazzia se lo fate.
Funzioni che chiamano se stesse
Possibilissimo. Si chiama ricorsione e consiste in una funzione che chiama se stessa all'interno della sua logica.
Prendiamo come esempio il fattoriale. In matematica il fattoriale è il prodotto degli interi positivi minori o uguali a n.
Per esempio:
17! = 7 * 6 * 5 * 4 * 3 * 2 * 1 = 5040
In JavaScript possiamo scrivere una funzione che calcola il fattoriale in questo modo:
1function fattoriale(n) {
2 if ((n === 0) || (n === 1)) {
3 return 1;
4 } else {
5 return (n * fattoriale(n - 1));
6 }
7}
8console.log(fattoriale(5)); // output: 120
Lo scope delle funzioni
Lo scope delle funzioni, come già ampiamente discusso nel video dedicato, non può essere manipolato o usato al di fuori della funzione stessa, ma la funzione può accedere a tutte le variabili e funzioni presenti nella scope dove è stata definita.
Le closure
Le funzioni possono essere anche annidate. Avevo anticipato questo concetto sempre nel mio video dello scope (un must see a quanto pare). La funzione interna ad un'altra funzione può essere usata solo da quest'ultima (si dice che è privata).
Questo annidamento forma una closure.
Le closure saranno oggetto di un video a parte, questo fa capire anche la complessità dell'argomento. Per ora ti basta sapere che ogni funzione in JavaScript ha una closure, la quale viene creata quando la funzione stessa viene definita la prima volta e non durante l'esecuzione. Senza questo meccanismo di accesso ai dati le implementazioni di callback (funzioni chiamate alla fine di un'altra funzione) o gestori di eventi sarebbe abbastanza complicate.
Il concetto di closure è strettamente legato al concetto di scope, ma non voglio aggiungere troppe complicanze ad un articolo già abbastanza ricco di concetti. Non ti resta che guardare il mio video quando lo pubblicherò :)
I parametri delle funzioni
Prendiamo come esempio una nuova funzione
1function moltiplicazione(multiplo1, multiplo2) {
2 return multiplo1 * multiplo2;
3}
Niente di troppo complicato, si tratta di una semplice funzione che fa la moltiplicazione.
In questo caso questa funzione, come quella della somma e del fattoriale viste in precedenza si aspettano dei parametri obbligatori. Questo significa che per far funzionare tutta la baracca bisogna passare per forza due valori da moltiplicare. Se omettessimo un parametro obbligatorio JavaScript ci segnalerebbe l'errore.
I parametri però non sono sempre obbligatori. Le funzioni possono avere anche ricevere zero parametri o parametri opzionali.
Funzioni senza parametri
Le funzioni senza parametri tra la coppia di parentesi tonde non hanno niente. Questo vuol dire che la logica della funzione non dipende da dei valori provenienti dall'esterno.
1function saluta() {
2 console.log("Ciao!");
3}
4
5saluta(); // Output: "Ciao!"
Funzioni con parametri opzionali
Le funzioni con parametri opzionali tra la coppia di parentesi tonde hanno i parametri necessari per funzionare, ma alcuni potrebbero avere dei valori di default che, nell'eventualità, possono essere sovrascritti.
1function mostraArticoliBlog(postPerPagina = 10) {
2 // Logica della funzione.
3}
4
5mostraArticoliBlog(); // Output: 10 articoli del blog
6mostraArticoliBlog(5); // Output: 5 articoli del blog
In questo caso potete vedere che ho chiamato la funzione in due modi distinti. Il primo per quanto la funzione accetti un parametro postPerPagina
non lo passo durante la chiamata. Per cui la funzione userà il valore di default (10).
Nel secondo caso invece il valore di default verrà sovrascritto da quello che ho passato in fase di chiamata e quindi verranno mostrati 5 articoli al posto di 10.
Altri modi per dichiarare una funzione
Finora abbiamo visto che le funzioni vengono dichiarate facendo seguire alla parola chiave function
il nome della funzione, le parantesi tonde, gli eventuali parametri, ecc. In questo modo noi stiamo dichiarando una "named" function.
JavaScript prevede diversi modi per dichiarare una funzione. Vediamoli.
Funzione anonima
A differenza delle "named" function. Le funzioni anonime non hanno nome.
1const miaFunzione = function() {
2 // Logica della funzione
3}
4
5miaFunzione();
Da notare è che per chiamare la funzione ho usato il nome della costante. L'uso delle funzioni anonime per quanto possibile non è una pratica sempre consigliata. Se dovessimo indagare su un errore che si è verificato nel nostro programma sarebbe difficile capire quale funzione ha causato il problema perché il browser ci direbbe che a causare l'errore è stata una funzione anonima.
Questo quindi è uno dei principali benefici nell'utilizzare delle funzioni con nome. Le quali possono essere passate ad una costante o variabile come visto nell'esempio precedente.
1const miaFunzione = function nomeDellaFunzione() {
2 // Logica della funzione
3}
4
5miaFunzione();
La differenza tra i due snippet è che se il secondo fa bordello la console del browser ci dirà il nome della funzione e non "anonimo".
Funzioni a chiamata immediata
Le IIFE (Immediately Invoked Function Expression) è un pattern molto comune per chiamare quelle funzioni che devono essere eseguite una sola volta durante l'esecuzione del programma.
1(function() {
2 // Logica
3})();
La funzione verrà eseguita immediatamente e non potrà essere richiamata perché anonima.
Arrow function
Ultime, ma non per importanza, ma per ordine cronologico d'ingresso nello standard ECMAScript sono le arrow function.
Le arrow function devono il loro nome al modo in cui vengono scritte e cioè in questo modo:
1const somma = (addendo1, addendo2) => addendo1 + addendo2;
La freccia (=>
) che separa i parametri dal corpo della funzione è la ragione per cui questo tipo di funzioni anonime vengono chiamate arrow function.
Avete letto bene, anonime. Questo significa che portano con se il problema delle loro sorelle con la parola chiave function
che abbiamo visto qualche paragrafo più in su. Questo non vuol dire che non bisogna utilizzarle. Le arrow function sono ottime per scrivere codice più conciso e semplice da leggere.
Nell'esempio che ho fatto vedere prima ho potuto omettere delle parti grazie proprio all'arrow function. Per esteso la funzione poteva essere scritta anche in questo modo:
1const somma = (addendo1, addendo2) => {
2 return addendo1 + addendo2;
3}
Questo è quanto c'è da sapere di base sulle funzioni, spero sia tutto chiaro. Grazie per aver letto. Stay Safe!
Caricamento...
Diventiamo amici di penna? ✒️
Iscriviti alla newsletter per ricevere una mail ogni paio di settimane con le ultime novità, gli ultimi approfondimenti e gli ultimi corsi gratuiti puubblicati. Ogni tanto potrei scrivere qualcosa di commerciale, ma solo se mi autorizzi, altrimenti non ti disturberò oltre.
Se non ti piace la newsletter ti ricordo la community su Discord, dove puoi chiedere aiuto, fare domande e condividere le tue esperienze (ma soprattutto scambiare due meme con me). Ti aspetto!