Metodi dei Primitivi JavaScript
Scopri come i primitivi JavaScript come stringhe, numeri, boolean, simboli e bigint possono chiamare metodi tramite wrapper object temporanei.
Introduzione ai Primitivi e agli Oggetti JavaScript
In JavaScript, quasi tutto ciò che scrivi riguarda un primitivo o un object. Capire la differenza — e l'ingegnoso trucco che permette ai primitivi di comportarsi come oggetti — è una delle basi fondamentali del linguaggio.
Un primitivo è il tipo di valore più semplice e indivisibile. Esistono sette tipi primitivi: numeri, stringhe, boolean, undefined, null, simboli e bigint. Un object è una raccolta di proprietà e metodi.
Ecco il problema che questa pagina risolve: una stringa è un primitivo privo di metodi, eppure "hello".toUpperCase() funziona. Come può un valore privo di metodi chiamarne uno? La risposta sono i wrapper object, e questo capitolo spiega esattamente come funzionano.
Questa pagina tratta cosa rende speciali i primitivi, come JavaScript li avvolge temporaneamente per permettere di chiamare metodi, i metodi disponibili per ciascun tipo primitivo e il comune errore di usare new con un costruttore primitivo.
Cosa Rende Unici i Primitivi
I primitivi si differenziano dagli oggetti in tre modi importanti.
1. Immutabilità. Una volta creato un valore primitivo, non può essere modificato. Un'operazione su una stringa non modifica mai la stringa originale — restituisce una nuova stringa. Tentare di assegnare un carattere non produce alcun effetto (e lancia un errore in strict mode):
2. Memorizzati per valore. Un primitivo è contenuto direttamente nella variabile. Quando lo copi, copi il valore stesso, quindi le due variabili sono del tutto indipendenti:
Gli oggetti, al contrario, sono memorizzati per riferimento — copiare la variabile copia solo un puntatore allo stesso object.
3. Semplici e leggeri. Un primitivo non possiede proprietà o metodi propri, il che lo rende veloce da creare e confrontare. Un boolean come let flag = true; è solo un valore, privo dell'overhead che avrebbe un object.
Gli Oggetti in JavaScript: un Confronto
Gli oggetti sono la struttura più complessa. A differenza dei primitivi, essi sono:
- Mutabili — il loro contenuto può essere modificato dopo la creazione.
- Tipi riferimento — gli oggetti sono memorizzati e copiati per riferimento, non per valore.
- Versatili — possono contenere funzioni, array e altri oggetti.
Come i Primitivi Chiamano i Metodi: i Wrapper Object
Quindi come funziona "hello".toUpperCase() se la stringa non ha metodi? Quando accedi a una proprietà o a un metodo su un primitivo, JavaScript:
- Crea un wrapper object temporaneo del tipo corrispondente che contiene il valore primitivo.
- Legge il metodo o la proprietà richiesta da quel wrapper.
- Lo esegue e restituisce il risultato.
- Scarta immediatamente il wrapper object.
L'intera operazione avviene dietro le quinte ed è fortemente ottimizzata dal motore, quindi è di fatto gratuita. Il punto chiave: il primitivo stesso non viene mai modificato e non diventa mai permanentemente un object — il wrapper esiste solo per la durata di quella singola espressione.
I Costruttori Wrapper
Cinque tipi primitivi dispongono di un costruttore wrapper integrato che fornisce i loro metodi:
- String — per i primitivi stringa.
- Number — per i valori numerici.
- Boolean — per i valori boolean.
- Symbol — per i simboli.
- BigInt — per i bigint.
null e undefined non hanno wrapper, quindi leggere una proprietà su di essi lancia un TypeError (ad esempio null.toString() fallisce).
Metodi delle Stringhe
Le stringhe espongono un ricco insieme di metodi tramite il wrapper String. Qui una coppia di essi si combina per trasformare in maiuscolo l'iniziale di ogni parola di una frase:
Nota che length è una proprietà, non un metodo, quindi non ha parentesi. toUpperCase() restituisce una nuova stringa e lascia greeting invariata, rispettando la regola di immutabilità sopra descritta.
Metodi dei Numeri
I numeri acquisiscono metodi dal wrapper Number. Uno dei più frequenti è toFixed(), che arrotonda a un numero fisso di decimali:
Due cose a cui prestare attenzione. Prima, toFixed() restituisce una stringa, non un numero — typeof (3.14159).toFixed(2) è "string". Seconda, per chiamare un metodo direttamente su un numero letterale è necessario usare parentesi aggiuntive o uno spazio: 255..toString(16) funziona anch'esso, ma 255.toString(16) è un errore di sintassi perché il parser interpreta il primo punto come separatore decimale.
Metodi dei Boolean
I boolean possono usare il wrapper Boolean, nella maggior parte dei casi solo toString():
Metodi dei Simboli
I simboli, un tipo primitivo unico, ottengono metodi dal wrapper Symbol:
Qui è necessario chiamare toString() esplicitamente — i simboli deliberatamente non si convertono automaticamente in stringa nei contesti stringa (come "" + sym), il che altrimenti lancerebbe un TypeError.
Metodi dei BigInt
BigInt, progettato per interi troppo grandi per il tipo Number normale, ottiene metodi dal wrapper BigInt:
Il valore viene passato come stringa perché scriverlo come letterale numerico supererebbe l'intervallo degli interi sicuri e perderebbe precisione prima che BigInt lo riceva.
Il Trabocchetto: Non Usare Mai new con i Wrapper Primitivi
JavaScript permette di costruire un wrapper object manualmente con new Number(1), new String("x") o new Boolean(false) — ma quasi mai dovresti farlo. Un wrapper creato con new è un vero object, e ogni object è truthy, incluso uno che avvolge false:
Questa è una classica fonte di bug. Chiamare il costruttore senza new è corretto e utile — Number("42"), String(123) e Boolean(value) eseguono una semplice conversione di tipo e restituiscono primitivi, non oggetti.
Riepilogo
- I primitivi sono valori semplici e immutabili memorizzati per valore; gli oggetti sono mutabili e memorizzati per riferimento.
- Chiamare un metodo su un primitivo funziona perché JavaScript lo avvolge in un object temporaneo, esegue il metodo, quindi scarta il wrapper.
String,Number,Boolean,SymboleBigIntforniscono i metodi;nulleundefinednon hanno wrapper e lanciano un errore se si accede a una proprietà.- Usa le funzioni wrapper senza
newper la conversione di tipo. Non usare mainewper creare wrapper object nel codice ordinario — sono sempre truthy e si comportano in modo inatteso.
Successivamente, esplora i metodi di ciascun tipo in dettaglio in stringhe, numeri e bigint.