Tipo Symbol in Javascript
- I Simboli sono un tipo di dato introdotto in ES6 per creare nomi di proprietà unici.
- I Simboli possono essere creati usando la funzione
Symbol()
, che restituisce un valore unico ogni volta che viene chiamata. - I Simboli possono essere usati come nomi di proprietà in oggetti, permettendo di evitare conflitti con altre proprietà.
- I Simboli non hanno una sintassi letterale e non possono essere concatenati come le stringhe.
- La funzione
Symbol.for()
permette di creare o recuperare un Simbolo condiviso a livello globale, associato a una stringa. - I Simboli hanno un metodo
toString()
che restituisce una rappresentazione testuale del Simbolo, e la funzioneSymbol.keyFor()
permette di recuperare la stringa associata a un Simbolo globale. - I Simboli sono utili per estendere il linguaggio senza rischiare di sovrascrivere proprietà esistenti in oggetti.
Symbol
I Simboli sono stati introdotti in ES6 per servire come nomi di proprietà non-stringa. Per comprendere i Simboli, è necessario sapere che il tipo Object fondamentale di JavaScript è una collezione non ordinata di proprietà, dove ogni proprietà ha un nome e un valore. I nomi delle proprietà sono tipicamente (e fino a ES6, erano esclusivamente) stringhe. Ma in ES6 e versioni successive, anche i Simboli possono servire a questo scopo:
let nomeStr = "nome stringa"; // Una stringa da usare come nome di proprietà
let nomeSim = Symbol("nomeprop"); // Un Simbolo da usare come nome di proprietà
typeof nomeStr // => "string": nomeStr è una stringa
typeof nomeSim // => "symbol": nomeSim è un simbolo
let o = {}; // Crea un nuovo oggetto
o[nomeStr] = 1; // Definisce una proprietà con un nome stringa
o[nomeSim] = 2; // Definisce una proprietà con un nome Simbolo
o[nomeStr] // => 1: accede alla proprietà con nome stringa
o[nomeSim] // => 2: accede alla proprietà con nome simbolo
Il tipo Symbol
non ha una sintassi letterale. Per ottenere un valore Symbol
, si chiama la funzione Symbol()
. Questa funzione non restituisce mai lo stesso valore due volte, anche quando chiamata con lo stesso argomento. Questo significa che se si chiama Symbol()
per ottenere un valore Symbol, è possibile utilizzare quel valore in sicurezza come nome di proprietà per aggiungere una nuova proprietà a un oggetto e non ci si deve preoccupare di sovrascrivere una proprietà esistente con lo stesso nome. Allo stesso modo, se si utilizzano nomi di proprietà simbolici e non si condividono quei simboli, si può essere sicuri che altri moduli di codice nel programma non sovrascriveranno accidentalmente le proprietà.
In pratica, i Simboli servono come meccanismo di estensione del linguaggio. Quando ES6 ha introdotto il ciclo for/of
, è stato necessario definire un metodo standard che le classi potessero implementare per rendersi iterabili. Ma standardizzare qualsiasi nome di stringa particolare per questo metodo iteratore avrebbe compromesso il codice esistente, quindi è stato utilizzato invece un nome simbolico.
La funzione Symbol()
accetta un argomento stringa opzionale e restituisce un valore Symbol unico. Se si fornisce un argomento stringa, quella stringa sarà inclusa nell'output del metodo toString()
del Symbol. Si noti, tuttavia, che chiamare Symbol()
due volte con la stessa stringa produce due valori Symbol completamente diversi.
let s = Symbol("sim_x");
s.toString() // => "Symbol(sim_x)"
toString()
è l'unico metodo interessante delle istanze Symbol. Ci sono tuttavia altre due funzioni correlate ai Symbol che si dovrebbero conoscere. A volte quando si utilizzano i Simboli, si vuole mantenerli privati al codice così si ha la garanzia che le proprietà non entreranno mai in conflitto con proprietà utilizzate da altro codice. Altre volte, tuttavia, si potrebbe voler definire un valore Symbol e condividerlo ampiamente con altro codice. Questo sarebbe il caso, per esempio, se si stesse definendo qualche tipo di estensione alla quale si vuole che altro codice possa partecipare.
Per questo ultimo caso d'uso, JavaScript definisce un registro Symbol globale. La funzione Symbol.for()
accetta un argomento stringa e restituisce un valore Symbol che è associato con la stringa che si passa. Se nessun Symbol è già associato con quella stringa, allora ne viene creato e restituito uno nuovo; altrimenti, viene restituito il Symbol già esistente. Cioè, la funzione Symbol.for()
è completamente diversa dalla funzione Symbol()
: Symbol()
non restituisce mai lo stesso valore due volte, ma Symbol.for()
restituisce sempre lo stesso valore quando chiamata con la stessa stringa. La stringa passata a Symbol.for()
appare nell'output di toString()
per il Symbol restituito, e può anche essere recuperata chiamando Symbol.keyFor()
sul Symbol restituito.
let s = Symbol.for("condiviso");
let t = Symbol.for("condiviso");
s === t // => true
s.toString() // => "Symbol(condiviso)"
Symbol.keyFor(t) // => "condiviso"