Impara a creare e utilizzare funzioni: dichiarazione, parametri, return e scope.
β Altri esempi: Approfondimento: funzioni, altri esempi.
Cos'Γ¨ una Funzione?
Una funzione Γ¨ un blocco di codice riutilizzabile che esegue un compito specifico. Invece di scrivere lo stesso codice piΓΉ volte, lo metti in una funzione e la chiami quando serve!
Funzioni nella Vita Reale
Pensa a una funzione come a una ricetta:
- Ingredienti β Parametri (input)
- Procedimento β Corpo della funzione (codice)
- Piatto finale β Valore di ritorno (output)
Una volta creata la "ricetta" (funzione), puoi usarla infinite volte senza riscriverla!
π― Vantaggi delle Funzioni
- β Riutilizzo - Scrivi una volta, usa ovunque
- β Organizzazione - Codice piΓΉ pulito e leggibile
- β Manutenzione - Modifica in un solo posto
- β Testing - PiΓΉ facile testare blocchi isolati
- β Astrazione - Nascondi la complessitΓ
Dichiarazione di Funzioni
Ci sono diversi modi per creare funzioni in JavaScript. Vediamo i principali.
- Function Declaration (Dichiarazione)
Il modo classico e piΓΉ comune. β CONSIGLIATO per iniziare
Dichiarazione Funzione
// Sintassi base
function nomeFunzione() {
// Codice da eseguire
}
// Esempio pratico
function saluta() {
console.log("Ciao! π");
}
// Chiamata (esecuzione) della funzione
saluta(); // Output: "Ciao! π"
// Puoi chiamarla piΓΉ volte
saluta(); // Output: "Ciao! π"
saluta(); // Output: "Ciao! π"
- Function Expression (Espressione)
Assegna una funzione a una variabile.
Espressione Funzione
// Funzione anonima assegnata a variabile
const saluta = function() {
console.log("Ciao! π");
};
// Chiamata
saluta(); // Output: "Ciao! π"
// Funzione con nome (opzionale)
const mostraBenvenuto = function benvenuto() {
console.log("Benvenuto!");
};
mostraBenvenuto();
π Declaration vs Expression
| Caratteristica | Declaration | Expression |
|---|---|---|
| Sintassi | function nome() {} |
const nome = function() {} |
| Hoisting | β SΓ¬ (disponibile prima) | β No |
| Quando usare | Funzioni globali/principali | Callback, funzioni assegnate |
π‘ Hoisting delle Funzioni
Le function declaration sono hoisted (sollevate) all'inizio dello scope, quindi puoi chiamarle prima di dichiararle!
// β
Funziona - Declaration
saluta(); // Output: "Ciao!"
function saluta() {
console.log("Ciao!");
}
// β ERRORE - Expression
// ciao(); // ReferenceError!
const ciao = function() {
console.log("Ciao!");
};
Parametri e Argomenti
I parametri sono le variabili nella definizione della funzione. Gli argomenti sono i valori passati quando la chiami.
- Funzioni con Parametri
Rendono le funzioni piΓΉ flessibili e riutilizzabili.
Parametri Base
// Funzione con un parametro
function saluta(nome) {
console.log(`Ciao ${nome}! π`);
}
saluta("Mario"); // Output: "Ciao Mario! π"
saluta("Anna"); // Output: "Ciao Anna! π"
// Funzione con piΓΉ parametri
function somma(a, b) {
console.log(a + b);
}
somma(5, 3); // Output: 8
somma(10, 20); // Output: 30
// Esempio pratico: Calcolo area rettangolo
function calcolaArea(base, altezza) {
let area = base * altezza;
console.log(`Area: ${area} mΒ²`);
}
calcolaArea(5, 10); // Output: "Area: 50 mΒ²"
calcolaArea(3, 7); // Output: "Area: 21 mΒ²"
- Parametri Predefiniti (Default Parameters)
Valori di default se l'argomento non viene passato (ES6).
Default Parameters
// Senza parametri default
function saluta(nome) {
console.log(`Ciao ${nome}!`);
}
saluta(); // Output: "Ciao undefined!"
// β
Con parametri default
function salutaDefault(nome = "Ospite") {
console.log(`Ciao ${nome}!`);
}
salutaDefault(); // Output: "Ciao Ospite!"
salutaDefault("Mario"); // Output: "Ciao Mario!"
// Esempio pratico
function calcolaPrezzo(prezzo, sconto = 0) {
let totale = prezzo - (prezzo * sconto / 100);
console.log(`Prezzo finale: β¬${totale}`);
}
calcolaPrezzo(100); // Output: "Prezzo finale: β¬100"
calcolaPrezzo(100, 20); // Output: "Prezzo finale: β¬80"
- Parametri Multipli e Rest Parameter
Gestisci un numero variabile di argomenti con ...rest.
Rest Parameter
// Somma di numeri variabili
function somma(...numeri) {
let totale = 0;
for (let numero of numeri) {
totale += numero;
}
return totale;
}
console.log(somma(1, 2, 3)); // 6
console.log(somma(5, 10, 15, 20)); // 50
console.log(somma(100)); // 100
// Combinazione parametri normali + rest
function presentati(nome, etΓ , ...hobbies) {
console.log(`Mi chiamo ${nome}, ho ${etΓ } anni`);
console.log(`I miei hobby: ${hobbies.join(", ")}`);
}
presentati("Mario", 30, "calcio", "lettura", "coding");
// Output:
// Mi chiamo Mario, ho 30 anni
// I miei hobby: calcio, lettura, coding
β οΈ Ordine dei Parametri
I parametri con default vanno sempre alla fine, altrimenti saltare argomenti diventa complicato.
// β MALE - Default all'inizio
function male(nome = "Ospite", etΓ ) {
console.log(`${nome}, ${etΓ } anni`);
}
male(25); // Output: "25, undefined anni" (confuso!)
// β
BENE - Default alla fine
function bene(etΓ , nome = "Ospite") {
console.log(`${nome}, ${etΓ } anni`);
}
bene(25); // Output: "Ospite, 25 anni" (chiaro!)
Valore di Ritorno (return)
L'istruzione return restituisce un valore dalla funzione e termina l'esecuzione.
- Return Base
Restituisci un valore per usarlo fuori dalla funzione.
Return Statement
// Funzione senza return (restituisce undefined)
function saluta() {
console.log("Ciao!");
}
let risultato1 = saluta();
console.log(risultato1); // undefined
// β
Funzione con return
function somma(a, b) {
return a + b;
}
let risultato2 = somma(5, 3);
console.log(risultato2); // 8
// Puoi usare il valore restituito
let totale = somma(10, 20) + somma(5, 15);
console.log(totale); // 50
- Return Termina la Funzione
Il codice dopo return non viene eseguito.
Return Exit
function controlla(numero) {
if (numero < 0) {
return "Negativo";
console.log("Non eseguito!"); // Mai raggiunto
}
if (numero === 0) {
return "Zero";
}
return "Positivo";
}
console.log(controlla(-5)); // "Negativo"
console.log(controlla(0)); // "Zero"
console.log(controlla(10)); // "Positivo"
// Return anticipato per validazione
function dividi(a, b) {
if (b === 0) {
return "Errore: divisione per zero";
}
return a / b;
}
console.log(dividi(10, 2)); // 5
console.log(dividi(10, 0)); // "Errore: divisione per zero"
- Return di Tipi Diversi
Puoi restituire qualsiasi tipo di dato.
Return Vari Tipi
// Return numero
function quadrato(n) {
return n * n;
}
// Return stringa
function nomeCompleto(nome, cognome) {
return `${nome} ${cognome}`;
}
// Return boolean
function isPari(numero) {
return numero % 2 === 0;
}
// Return array
function creaArray(n) {
let arr = [];
for (let i = 1; i <= n; i++) {
arr.push(i);
}
return arr;
}
// Return oggetto
function creaUtente(nome, etΓ ) {
return {
nome: nome,
etΓ : etΓ ,
adulto: etΓ >= 18
};
}
// Test
console.log(quadrato(5)); // 25
console.log(nomeCompleto("Mario", "Rossi")); // "Mario Rossi"
console.log(isPari(4)); // true
console.log(creaArray(5)); // [1, 2, 3, 4, 5]
console.log(creaUtente("Anna", 25));
// {nome: "Anna", etΓ : 25, adulto: true}
π‘ Return vs Console.log
return restituisce un valore utilizzabile,
console.log solo mostra a schermo!
// Solo console.log - NON restituisce valore
function somma1(a, b) {
console.log(a + b);
}
let x = somma1(5, 3); // Stampa: 8
console.log(x); // undefined (nessun return!)
// β
Con return - RESTITUISCE valore
function somma2(a, b) {
return a + b;
}
let y = somma2(5, 3); // Non stampa nulla
console.log(y); // 8 (valore restituito!)
console.log(y * 2); // 16 (posso usarlo!)
Scope (Ambito)
Lo scope determina dove le variabili sono accessibili nel codice.
- Scope Globale vs Locale
Variabili globali: accessibili ovunque. Locali: solo nella funzione.
Global vs Local Scope
// Variabile GLOBALE
let globale = "Sono globale";
function esempio() {
// Variabile LOCALE
let locale = "Sono locale";
console.log(globale); // β
Accesso OK
console.log(locale); // β
Accesso OK
}
esempio();
console.log(globale); // β
Accesso OK
// console.log(locale); // β ERRORE! Non definita fuori
// Esempio pratico
let contatore = 0; // Globale
function incrementa() {
let incremento = 1; // Locale
contatore += incremento;
}
incrementa();
incrementa();
console.log(contatore); // 2
// console.log(incremento); // β ERRORE!
- Parametri Come Variabili Locali
I parametri esistono solo dentro la funzione.
Scope Parametri
function saluta(nome) {
// 'nome' esiste SOLO qui dentro
console.log(`Ciao ${nome}!`);
}
saluta("Mario");
// console.log(nome); // β ERRORE! nome non definito
// Shadowing - variabile locale nasconde globale
let numero = 10; // Globale
function test() {
let numero = 5; // Locale (diversa!)
console.log(numero); // 5 (locale)
}
test();
console.log(numero); // 10 (globale invariata)
- Block Scope con let e const
let e const hanno scope di blocco (if, for, while...).
Block Scope
function esempio() {
let x = 1;
if (true) {
let x = 2; // Diversa variabile (block scope)
console.log(x); // 2
}
console.log(x); // 1
}
esempio();
// var NON ha block scope (evita var!)
function esempioVar() {
var y = 1;
if (true) {
var y = 2; // STESSA variabile!
console.log(y); // 2
}
console.log(y); // 2 (modificata!)
}
esempioVar();
π Regole dello Scope
Globale
- Accessibile ovunque
- Dichiarata fuori funzioni
- Evita troppi globali!
Funzione
- Solo dentro la funzione
- Parametri inclusi
- Isolamento codice
Blocco
- Solo nel blocco {}
- let e const
- if, for, while
Esempio Completo: Calcolatrice
Sistema Calcolatrice Completo
// Calcolatrice con funzioni
const calcolatrice = {
// Operazioni base
somma: function(a, b) {
return a + b;
},
sottrai: function(a, b) {
return a - b;
},
moltiplica: function(a, b) {
return a * b;
},
dividi: function(a, b) {
if (b === 0) {
return "Errore: divisione per zero";
}
return a / b;
},
// Operazioni avanzate
potenza: function(base, esponente) {
return Math.pow(base, esponente);
},
percentuale: function(numero, percentuale) {
return (numero * percentuale) / 100;
},
media: function(...numeri) {
if (numeri.length === 0) {
return 0;
}
let somma = 0;
for (let num of numeri) {
somma += num;
}
return somma / numeri.length;
}
};
// Funzione helper per formattare risultati
function mostraRisultato(operazione, risultato) {
console.log(`${operazione} = ${risultato}`);
console.log("β".repeat(40));
}
// Funzione menu
function eseguiCalcolo(operazione, ...valori) {
let risultato;
switch(operazione.toLowerCase()) {
case "somma":
risultato = calcolatrice.somma(valori[0], valori[1]);
mostraRisultato(`${valori[0]} + ${valori[1]}`, risultato);
break;
case "sottrai":
risultato = calcolatrice.sottrai(valori[0], valori[1]);
mostraRisultato(`${valori[0]} - ${valori[1]}`, risultato);
break;
case "moltiplica":
risultato = calcolatrice.moltiplica(valori[0], valori[1]);
mostraRisultato(`${valori[0]} Γ ${valori[1]}`, risultato);
break;
case "dividi":
risultato = calcolatrice.dividi(valori[0], valori[1]);
mostraRisultato(`${valori[0]} Γ· ${valori[1]}`, risultato);
break;
case "potenza":
risultato = calcolatrice.potenza(valori[0], valori[1]);
mostraRisultato(`${valori[0]}^${valori[1]}`, risultato);
break;
case "percentuale":
risultato = calcolatrice.percentuale(valori[0], valori[1]);
mostraRisultato(`${valori[1]}% di ${valori[0]}`, risultato);
break;
case "media":
risultato = calcolatrice.media(...valori);
mostraRisultato(`Media di ${valori.join(", ")}`, risultato.toFixed(2));
break;
default:
console.log("Operazione non riconosciuta");
return;
}
return risultato;
}
// Test della calcolatrice
console.log("=== CALCOLATRICE ===\n");
eseguiCalcolo("somma", 15, 7);
eseguiCalcolo("sottrai", 20, 8);
eseguiCalcolo("moltiplica", 6, 7);
eseguiCalcolo("dividi", 50, 5);
eseguiCalcolo("potenza", 2, 8);
eseguiCalcolo("percentuale", 200, 15);
eseguiCalcolo("media", 10, 20, 30, 40, 50);
// Output:
// === CALCOLATRICE ===
//
// 15 + 7 = 22
// ββββββββββββββββββββββββββββββββββββββββ
// 20 - 8 = 12
// ββββββββββββββββββββββββββββββββββββββββ
// 6 Γ 7 = 42
// ββββββββββββββββββββββββββββββββββββββββ
// 50 Γ· 5 = 10
// ββββββββββββββββββββββββββββββββββββββββ
// 2^8 = 256
// ββββββββββββββββββββββββββββββββββββββββ
// 15% di 200 = 30
// ββββββββββββββββββββββββββββββββββββββββ
// Media di 10, 20, 30, 40, 50 = 30.00
// ββββββββββββββββββββββββββββββββββββββββ
π‘ Concetti Utilizzati
- Funzioni come metodi di oggetto
- Parametri multipli
- Return per restituire valori
- Rest parameter (
...numeri) - Validazione input (divisione per zero)
- Funzioni helper per formattazione
- Switch per routing operazioni
Esercizi Pratici
Esercizio 1: Convertitore Temperature
Obiettivo: Crea funzioni per convertire temperature
celsiusToFahrenheit(celsius)β FahrenheitfahrenheitToCelsius(fahrenheit)β CelsiuscelsiusToKelvin(celsius)β Kelvin- Formule: F = (C Γ 9/5) + 32, K = C + 273.15
Mostra la soluzione
Soluzione Esercizio 1
// Celsius β Fahrenheit
function celsiusToFahrenheit(celsius) {
return (celsius * 9/5) + 32;
}
// Fahrenheit β Celsius
function fahrenheitToCelsius(fahrenheit) {
return (fahrenheit - 32) * 5/9;
}
// Celsius β Kelvin
function celsiusToKelvin(celsius) {
return celsius + 273.15;
}
// Funzione universale
function convertiTemperatura(valore, da, a) {
// Normalizza a Celsius
let celsius;
switch(da.toLowerCase()) {
case "c":
celsius = valore;
break;
case "f":
celsius = fahrenheitToCelsius(valore);
break;
case "k":
celsius = valore - 273.15;
break;
default:
return "UnitΓ non valida";
}
// Converti a unitΓ richiesta
switch(a.toLowerCase()) {
case "c":
return celsius;
case "f":
return celsiusToFahrenheit(celsius);
case "k":
return celsiusToKelvin(celsius);
default:
return "UnitΓ non valida";
}
}
// Test
console.log("=== CONVERTITORE TEMPERATURE ===");
console.log(`0Β°C = ${celsiusToFahrenheit(0)}Β°F`);
console.log(`32Β°F = ${fahrenheitToCelsius(32)}Β°C`);
console.log(`0Β°C = ${celsiusToKelvin(0)}K`);
console.log("\nConversioni multiple:");
console.log(`100Β°C β ${convertiTemperatura(100, "C", "F")}Β°F`);
console.log(`100Β°C β ${convertiTemperatura(100, "C", "K")}K`);
// Output:
// === CONVERTITORE TEMPERATURE ===
// 0Β°C = 32Β°F
// 32Β°F = 0Β°C
// 0Β°C = 273.15K
//
// Conversioni multiple:
// 100Β°C β 212Β°F
// 100Β°C β 373.15K
Esercizio 2: Validatore Password
Obiettivo: Crea una funzione che valida password
- Lunghezza minima 8 caratteri
- Almeno una lettera maiuscola
- Almeno una lettera minuscola
- Almeno un numero
- Return oggetto con {valida: bool, errori: array}
Mostra la soluzione
Soluzione Esercizio 2
function validaPassword(password) {
let errori = [];
// Controllo lunghezza
if (password.length < 8) {
errori.push("Deve contenere almeno 8 caratteri");
}
// Controllo maiuscola
if (!/[A-Z]/.test(password)) {
errori.push("Deve contenere almeno una lettera maiuscola");
}
// Controllo minuscola
if (!/[a-z]/.test(password)) {
errori.push("Deve contenere almeno una lettera minuscola");
}
// Controllo numero
if (!/[0-9]/.test(password)) {
errori.push("Deve contenere almeno un numero");
}
return {
valida: errori.length === 0,
errori: errori
};
}
// Funzione per mostrare risultato
function mostraValidazione(password) {
console.log(`\nPassword: "${password}"`);
let risultato = validaPassword(password);
if (risultato.valida) {
console.log("β
Password valida!");
} else {
console.log("β Password non valida:");
risultato.errori.forEach((errore, i) => {
console.log(` ${i + 1}. ${errore}`);
});
}
}
// Test
console.log("=== VALIDATORE PASSWORD ===");
mostraValidazione("abc");
mostraValidazione("abcdefgh");
mostraValidazione("Abcdefgh");
mostraValidazione("Abcdefgh123");
// Output:
// === VALIDATORE PASSWORD ===
//
// Password: "abc"
// β Password non valida:
// 1. Deve contenere almeno 8 caratteri
// 2. Deve contenere almeno una lettera maiuscola
// 3. Deve contenere almeno un numero
//
// Password: "abcdefgh"
// β Password non valida:
// 1. Deve contenere almeno una lettera maiuscola
// 2. Deve contenere almeno un numero
//
// Password: "Abcdefgh"
// β Password non valida:
// 1. Deve contenere almeno un numero
//
// Password: "Abcdefgh123"
// β
Password valida!
Esercizio 3: Generatore Numeri Casuali
Obiettivo: Crea funzioni per numeri random
random(min, max)β numero casuale tra min e maxrandomArray(n, min, max)β array di n numeri casualilanciaDado()β numero 1-6lanciaDadi(n)β somma di n dadi
Mostra la soluzione
Soluzione Esercizio 3
// Numero casuale tra min e max (inclusi)
function random(min, max) {
return Math.floor(Math.random() * (max - min + 1)) + min;
}
// Array di numeri casuali
function randomArray(n, min, max) {
let arr = [];
for (let i = 0; i < n; i++) {
arr.push(random(min, max));
}
return arr;
}
// Lancia un dado (1-6)
function lanciaDado() {
return random(1, 6);
}
// Lancia n dadi e restituisce somma
function lanciaDadi(n = 2) {
let somma = 0;
let dadi = [];
for (let i = 0; i < n; i++) {
let dado = lanciaDado();
dadi.push(dado);
somma += dado;
}
return {
dadi: dadi,
somma: somma
};
}
// Simulazione lancio moneta
function lanciaMone() {
return random(0, 1) === 0 ? "Testa" : "Croce";
}
// Test
console.log("=== GENERATORE NUMERI CASUALI ===\n");
console.log("Numero casuale (1-100):", random(1, 100));
console.log("Array 5 numeri (1-10):", randomArray(5, 1, 10));
console.log("Lancio dado:", lanciaDado());
let risultato = lanciaDadi(3);
console.log(`\nLancio 3 dadi: ${risultato.dadi.join(" + ")}`);
console.log(`Somma: ${risultato.somma}`);
console.log("\nLancio moneta:");
for (let i = 0; i < 5; i++) {
console.log(` Lancio ${i + 1}: ${lanciaMone()}`);
}
// Output (esempio, varia):
// === GENERATORE NUMERI CASUALI ===
//
// Numero casuale (1-100): 47
// Array 5 numeri (1-10): [3, 8, 2, 9, 5]
// Lancio dado: 4
//
// Lancio 3 dadi: 5 + 2 + 6
// Somma: 13
//
// Lancio moneta:
// Lancio 1: Testa
// Lancio 2: Croce
// Lancio 3: Croce
// Lancio 4: Testa
// Lancio 5: Testa
π― Riepilogo Lezione
Dichiarazione:
- function nome() {}
- Hoisting β
- Uso generale
Parametri:
- Input funzione
- Default values
- Rest parameter
Return:
- Output funzione
- Termina esecuzione
- Qualsiasi tipo
Scope:
- Globale
- Funzione
- Blocco (let/const)