Símbolo

Los símbolos son una primitiva relativamente nueva que se introdujo en ES6. Una primitiva de símbolo representa un valor único que nunca coincide con ningún otro valor, incluidos los de otras primitivas de símbolos. Dos primitivas de string compuestas por caracteres idénticos se evalúan como estrictamente iguales:

String() === String()
> true

String( "My string." ) === String( "My string." );
> true

Sin embargo, ningún símbolo creado con la función Symbol() puede ser estrictamente igual:

Symbol() === Symbol()
> false

Esta característica te permite usar símbolos como claves de propiedad ú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
> Object { Symbol("Desc"): "propSymbol" }

Hay tres tipos de símbolos:

  • Símbolos creados con Symbol()
  • Símbolos compartidos que se configuran y recuperan de un registro de símbolos global con Symbol.for()
  • Los "símbolos conocidos" se definen como propiedades estáticas del 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 para fines de depuración y no afectan la unicidad del resultado. Todas las llamadas a Symbol muestran un tipo primitivo de símbolo completamente único, 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 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 se pueden enumerar, 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() otorga acceso a las propiedades de los símbolos de un objeto.

Símbolos compartidos

El método Symbol.for() intenta buscar cualquier símbolo existente en un registro de símbolos global de todo el entorno de ejecución con una cadena determinada como clave y muestra el símbolo coincidente si se encuentra uno. Si no lo encuentra, 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 ninguna 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, a la vez que evitan que el comportamiento principal se reemplace involuntariamente.

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 ()

Dado que los símbolos son una función específica de ES6, estos valores simbólicos se deben usar como "puntos de extensión" para los desarrolladores que modifican el comportamiento de JavaScript sin introducir problemas de retrocompatibilidad.

Los valores de símbolos conocidos suelen estilizarse con un prefijo @@ o unidos 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 tus conocimientos

¿Puedes usar new para crear un símbolo?

No

¿Cuáles de las siguientes opciones describen símbolos "reconocidos"?

Propiedades estáticas del objeto "Symbol"
Símbolos que usas con frecuencia
Claves de propiedad únicas para acceder a los métodos integrados de JavaScript y modificarlos