JavaScript — Classi ES6

constructor · metodi · ereditarietà · extends/super · 2026 · Marco Consiglio
Volta Institute · Napoli
A.A. 2026
🏗️ Cos'è una classe — un "modello" per creare oggetti simili
Una class (ES6) è un modello (template) per creare più oggetti che condividono la stessa struttura e comportamento. Il constructor è un metodo speciale eseguito automaticamente ogni volta che crei un nuovo oggetto dalla classe.
class Studente { constructor(nome, corso) { this.nome = nome; // this si riferisce al nuovo oggetto in creazione this.corso = corso; this.voti = []; } } const marco = new Studente('Marco', 'Full Stack'); console.log(marco.nome); // → 'Marco' console.log(marco.corso); // → 'Full Stack'
💡 La keyword new è ciò che crea davvero un nuovo oggetto (chiamato "istanza") a partire dalla classe, eseguendo automaticamente il constructor con gli argomenti passati.
🏭 Ogni istanza è indipendente
const marco = new Studente('Marco', 'Full Stack'); const giulia = new Studente('Giulia', 'Contabilità'); marco.voti.push(28); console.log(marco.voti); // → [28] console.log(giulia.voti); // → [] (completamente indipendente da marco!)
✅ Ogni oggetto creato con new ha le proprie proprietà separate: modificare marco.voti non ha alcun effetto su giulia.voti, anche se entrambi provengono dalla stessa classe.
⚙️ Metodi — le azioni che gli oggetti sanno fare
Un metodo è una funzione definita dentro la classe, condivisa da tutte le istanze — non serve riscriverla in ogni oggetto, esiste una sola volta a livello di classe.
class Studente { constructor(nome) { this.nome = nome; this.voti = []; } aggiungiVoto(voto) { this.voti.push(voto); } calcolaMedia() { if (this.voti.length === 0) return 0; return this.voti.reduce((tot, v) => tot + v, 0) / this.voti.length; } } const marco = new Studente('Marco'); marco.aggiungiVoto(28); marco.aggiungiVoto(30); console.log(marco.calcolaMedia()); // → 29
💡 Nota come calcolaMedia() riusa il metodo reduce() già visto nella guida sugli Array — le classi organizzano il codice, ma dentro i metodi usi sempre gli stessi strumenti JavaScript standard.
🧬 Ereditarietà — una classe che estende un'altra
extends permette a una classe di ereditare proprietà e metodi da un'altra classe (chiamata "classe base" o "genitore"), aggiungendo o modificando solo ciò che serve.
class Persona { constructor(nome) { this.nome = nome; } presentati() { console.log(`Sono ${this.nome}`); } } class Studente extends Persona { constructor(nome, corso) { super(nome); // chiama il constructor della classe GENITORE (Persona) this.corso = corso; } } const marco = new Studente('Marco', 'Full Stack'); marco.presentati(); // → 'Sono Marco' (metodo EREDITATO da Persona, mai riscritto in Studente!) console.log(marco.corso); // → 'Full Stack' (proprietà specifica di Studente)
✅ Studente "eredita" gratuitamente il metodo presentati() da Persona, senza doverlo riscrivere — questo evita duplicazione di codice tra classi che condividono caratteristiche comuni.
📞 super — chiamare il constructor (o i metodi) del genitore
super(...) nel constructor chiama il constructor della classe genitore, passandogli gli argomenti necessari. È obbligatorio chiamarlo prima di usare this in una classe che usa extends.
class Studente extends Persona { constructor(nome, corso) { super(nome); // ⚠️ deve essere la PRIMA istruzione, prima di ogni uso di 'this' this.corso = corso; } // Puoi anche "sovrascrivere" (override) un metodo del genitore: presentati() { super.presentati(); // chiama comunque la versione originale del genitore... console.log(`Studio ${this.corso}`); // ...e aggiunge qualcosa in più } } const marco = new Studente('Marco', 'Full Stack'); marco.presentati(); // → Sono Marco // → Studio Full Stack
⚠️ Se dimentichi super(nome) in una classe che estende un'altra, JavaScript genera un errore appena provi a usare this nel constructor — la chiamata a super deve avvenire prima di qualsiasi riferimento a this.
🔒 Campi privati — proteggere dati interni con #
Il prefisso # (introdotto più di recente) crea campi privati: accessibili solo dall'interno della classe stessa, non modificabili direttamente dall'esterno — un modo più diretto rispetto alle closure per ottenere incapsulamento.
class ContoBancario { #saldo; // campo privato, dichiarato con # constructor(saldoIniziale) { this.#saldo = saldoIniziale; } deposita(importo) { this.#saldo += importo; } controllaSaldo() { return this.#saldo; } } const conto = new ContoBancario(100); conto.deposita(50); console.log(conto.controllaSaldo()); // → 150 console.log(conto.#saldo); // → SyntaxError! #saldo non è accessibile da fuori la classe
💡 Questo risolve con sintassi nativa lo stesso problema visto con le closure (guida precedente): dati che devono essere modificabili solo attraverso metodi controllati, non direttamente dall'esterno.
🧪 Playground — prova le classi dal vivo
Editor JS
// il risultato apparirà qui