Una primitiva de símbolo representa un valor único que nunca choca con ningún otro valor, incluido el valor de otras primitivas de símbolo. Dos primitivas de cadenas que se componen de caracteres idénticos se evalúan como estrictamente iguales:
String() === String()
> true
String( "My string." ) === String( "My string." );
> true
Sin embargo, no hay dos símbolos creados con la función Symbol()
que puedan ser
estrictamente iguales:
Symbol() === Symbol()
> false
Esta característica te permite usar símbolos como claves de propiedades únicas en un objeto, lo que evita colisiones con claves que cualquier otro código podría agregar a ese objeto.
const mySymbol = Symbol( "Desc" );
const myObject = {};
myObject[mySymbol] = "propSymbol";
myObject
> Object { Symbol("Desc"): "propSymbol" }
Existen tres tipos de símbolos:
- Símbolos creados con
Symbol()
- Símbolos compartidos que se establecen y recuperan desde un registro de símbolos global con
Symbol.for()
- "Símbolos conocidos" definidos como propiedades estáticas en el objeto Symbol. Estos símbolos contienen métodos internos que no se pueden reemplazar accidentalmente.
Symbol()
acepta una descripción (o "nombre del símbolo") como argumento opcional.
Estas descripciones son etiquetas legibles por humanos para depurar y no afectan la unicidad del resultado. Cualquier llamada a Symbol
muestra una primitiva de símbolo completamente única, incluso si varias llamadas tienen descripciones idénticas:
Symbol( "My symbol." ) === Symbol( "My symbol." );
> false
Al igual que con otros tipos de datos primitivos, los símbolos heredan métodos y propiedades de su prototipo. Por ejemplo, puedes acceder a una descripción como una propiedad heredada del símbolo creado:
let mySymbol = Symbol( "My symbol." );
mySymbol.description
> "My symbol."
Sin embargo, no puedes crear un símbolo con la palabra clave new
:
let mySymbol = new Symbol();
> Uncaught TypeError: Symbol is not a constructor
Los símbolos no son enumerables, lo que significa que las propiedades simbólicas no están disponibles cuando se usan métodos estándar para iterar sobre ellas. El método getOwnPropertySymbols()
brinda acceso a las propiedades de símbolo de un objeto.
Símbolos compartidos
El método Symbol.for()
intenta buscar cualquier símbolo existente en un registro de símbolos global en todo el entorno de ejecución con una cadena determinada como clave y muestra el símbolo coincidente si se encuentra uno. Si no encuentra uno, crea un símbolo con la clave especificada y la agrega al registro global:
let sharedSymbol = Symbol.for( "My key." );
sharedSymbol === Symbol.for( "My key." )
> true
Estas claves no comparten superposición funcional con las descripciones asignadas a las primitivas Symbol
creadas por el autor. Para acceder a un símbolo en el registro de símbolos,
primero debes crearlo con for()
:
Symbol( "String" ) === Symbol( "String" );
> false
Symbol( "String" ) === Symbol.for( "String" );
> false
Symbol.for( "String" ) === Symbol.for( "String" );
> true
Para recuperar la clave de cualquier símbolo del registro de símbolos, usa Symbol.keyFor()
:
let mySymbol = Symbol.for( "Key." );
Symbol.keyFor( mySymbol ) ;
> "Key."
Símbolos "conocidos"
Los símbolos conocidos son propiedades estáticas del objeto Symbol
, cada una de las cuales es un símbolo. Los símbolos conocidos proporcionan claves de propiedad únicas para acceder a los métodos integrados de JavaScript y modificarlos, al tiempo que evitan que se reemplace el comportamiento principal de forma no intencional.
Symbol;
> function Symbol()
asyncIterator: Symbol(Symbol.asyncIterator)
for: function for()
hasInstance: Symbol("Symbol.hasInstance")
isConcatSpreadable: Symbol("Symbol.isConcatSpreadable")
iterator: Symbol(Symbol.iterator)
keyFor: function keyFor()
length: 0
match: Symbol("Symbol.match")
matchAll: Symbol("Symbol.matchAll")
name: "Symbol"
prototype: Object { … }
replace: Symbol("Symbol.replace")
search: Symbol("Symbol.search")
species: Symbol("Symbol.species")
split: Symbol("Symbol.split")
toPrimitive: Symbol("Symbol.toPrimitive")
toStringTag: Symbol("Symbol.toStringTag")
unscopables: Symbol("Symbol.unscopables")
<prototype>: function ()
Debido a que los símbolos son una función específica de ES6, estos valores simbólicos están destinados a usarse como "puntos de extensión" para que los desarrolladores modifiquen el comportamiento de JavaScript sin introducir problemas de retrocompatibilidad.
Los valores de símbolos conocidos suelen estilizarse con un
prefijo @@
o unirse en %
para
diferenciar sus claves de sus prototipos mutables. Por ejemplo, @@match
(o %match%
) es una referencia al Symbol.match
inmutable, no a String.prototype.match
.
Verifica tu comprensión
¿Puedes usar new
para crear un símbolo?
¿Cuál de las siguientes opciones describe símbolos “conocidos”?