W3docs

Membri Privati e Protetti delle Classi JavaScript

Scopri i membri privati con prefisso # e la convenzione _ per i membri protetti nelle classi JavaScript, con getter, setter e best practice.

Una classe spesso ha bisogno di nascondere alcune parti del suo funzionamento interno, in modo che il codice esterno non possa leggerle o modificarle direttamente. Questa pagina illustra i due modi che JavaScript offre per farlo: i membri veramente privati dichiarati con il prefisso #, e la convenzione del trattino basso _ che gli sviluppatori usano per segnalare che un membro è "protetto" (destinato solo alla classe e alle sue sottoclassi).

Vedrai quando usare ciascuno dei due approcci, perché i campi # sono genuinamente inaccessibili dall'esterno, e come combinare i campi privati con i getter e setter per esporre un'interfaccia controllata e validata. Se le classi sono nuove per te, inizia prima con il capitolo sulla sintassi base delle classi.

Introduzione all'Incapsulamento in JavaScript

L'incapsulamento è un principio fondamentale della programmazione orientata agli oggetti (OOP): raggruppa i dati (variabili) e i metodi (funzioni) che operano su tali dati in un'unica unità — un oggetto — e controlla l'accesso agli elementi interni di quell'oggetto. L'obiettivo è esporre un'interfaccia pubblica piccola e deliberata, nascondendo i dettagli implementativi dietro di essa.

Perché è importante? Quando lo stato interno è nascosto, il codice esterno non può portare l'oggetto in uno stato non valido, e sei libero di modificare il funzionamento interno della classe senza rompere il codice che la utilizza. In JavaScript, l'incapsulamento si ottiene con campi e metodi privati #. JavaScript non ha un modificatore protected nativo, quindi gli sviluppatori lo simulano con una convenzione di denominazione (il prefisso _), come spiegato di seguito.

Proprietà e Metodi Privati

Un membro privato di una classe viene dichiarato con il prefisso # nel nome. Può essere accessibile solo dall'interno del corpo della classe — qualsiasi tentativo di leggerlo o scriverlo dall'esterno è un errore di sintassi rigido, non semplicemente undefined. Questa è una vera privacy imposta dal linguaggio.

Un campo deve essere dichiarato nel corpo della classe prima di poter essere utilizzato (non è possibile creare un campo # al volo all'interno del costruttore come si può fare con una proprietà pubblica). Si noti inoltre che i campi privati # sono non-enumerabili: non compaiono in Object.keys(), in for...in, né nell'output di JSON.stringify().

javascript— editable

Perché # è veramente privato

A differenza della convenzione del trattino basso, un campo # è invisibile all'esterno della classe. Non è possibile accedervi tramite user.#name, tramite l'accesso con parentesi quadre come user["#name"], né tramite Object.keys(). La prima forma è un errore di sintassi; le altre semplicemente non trovano il campo.

javascript— editable

Metodi Privati

Anche i metodi possono essere privati: basta aggiungere il prefisso # al nome del metodo. Un metodo privato è utile per le funzioni di supporto interne che i chiamanti non dovrebbero mai invocare direttamente — ad esempio, la logica di validazione o formattazione che supporta l'API pubblica ma non ne fa parte.

javascript— editable

Proprietà e Metodi Protetti (la convenzione _)

JavaScript non ha la parola chiave protected. Per convenzione, un membro destinato ad essere usato dalla classe e dalle sue sottoclassi — ma non dal codice esterno — viene prefissato con un singolo trattino basso _. Questo è puramente un segnale per gli altri sviluppatori; un membro con _ rimane completamente leggibile e scrivibile da qualsiasi punto. Sceglilo quando le sottoclassi necessitano dell'accesso (un campo # non è accessibile dalle sottoclassi), accettando che la protezione sia per accordo, non per imposizione.

javascript— editable

Poiché i membri con _ vengono ereditati come qualsiasi normale proprietà, una sottoclasse può fare affidamento su di essi. Questo è il motivo pratico per usare la convenzione invece di # quando si progetta per l'ereditarietà:

javascript— editable

Incapsulamento Basato sugli Accessor: Best Practice

Quando si integrano proprietà e metodi privati e protetti nei propri progetti JavaScript, è utile seguire le seguenti best practice per massimizzarne i benefici:

  • Usa i campi privati per i dati sensibili o invarianti: Memorizza tutto ciò che non deve essere toccato direttamente — contatori interni, valori memorizzati nella cache, stato grezzo — come campo #. Questo garantisce l'integrità e previene effetti collaterali indesiderati.
  • Sfrutta i getter e setter: Mantieni il campo privato ed esponilo tramite un getter e setter. Il setter è l'occasione per validare o trasformare l'input prima che raggiunga il campo privato, in modo che l'oggetto non possa mai contenere un valore non valido.

Nell'esempio seguente, #age può essere modificato solo tramite il setter, che rifiuta i numeri negativi:

javascript— editable

Puoi anche esporre uno stato di sola lettura definendo un getter senza il corrispondente setter — il consumatore può leggere il valore ma non ha modo di sovrascrivere il campo privato sottostante.

  • Usa i membri protetti per l'ereditarietà: Usa proprietà e metodi protetti quando intendi renderli accessibili nelle sottoclassi. Questa strategia favorisce una struttura più flessibile e gerarchica nelle tue applicazioni.

Tecniche e Pattern Avanzati

Oltre alle basi, JavaScript consente pattern e tecniche sofisticate per incapsulare e strutturare ulteriormente il codice in modo efficace:

  • Pattern modulo: Usa le closure e le espressioni di funzione immediatamente invocate (IIFE) per creare ambiti privati.
  • Factory function: Queste funzioni restituiscono nuovi oggetti, permettendo dati privati tramite closure, senza la necessità della parola chiave new.
  • Proxy: I Proxy JavaScript possono essere usati per creare wrapper protettivi attorno agli oggetti, controllando l'accesso alle loro proprietà e metodi.

Conclusione

Usa i campi e i metodi # quando vuoi una privacy genuina e imposta che nessun codice esterno possa raggiungere. Usa la convenzione del trattino basso _ quando le sottoclassi necessitano dell'accesso e la protezione può essere per accordo. Combina i campi privati con getter e setter per esporre un'interfaccia controllata e validata — e getter di sola lettura quando lo stato deve essere osservabile ma non modificabile.

Argomenti correlati

Esercizio

Pratica
Quali affermazioni sono vere riguardo alle proprietà e ai metodi privati e protetti in JavaScript?
Quali affermazioni sono vere riguardo alle proprietà e ai metodi privati e protetti in JavaScript?
Was this page helpful?