javascript-tipo-symbol

El tipo Symbol en JavaScript

Un Symbol es un tipo de dato primitivo en JavaScript que representa un identificador único y persistente.

A diferencia de otros tipos de datos primitivos como number, string o boolean, los símbolos son siempre únicos.

Esto significa que cada vez que creas un nuevo símbolo, obtienes un valor distinto que no se puede duplicar

  • Unicidad: Cada Symbol es único e inmutable, lo que significa que dos símbolos nunca serán iguales.
  • No ennumerabilidad: Las propiedades de tipo Symbol no son enumerables por defecto, lo que significa que no aparecerán en operaciones como for...in.

El tipo de dato Symbol es uno de los tipos más avanzados y menos comprendidos, pero ofrece características útiles en ciertos contextos.

Creación de un Symbol

Para crear un Symbol, simplemente utilizamos la función constructora Symbol() sin la palabra clave new.

const mySymbol = Symbol();

En este ejemplo, id es un nuevo Symbol único e inmutable.

Descripción de un Symbol

Es posible proporcionar una descripción opcional al crear un Symbol. Esta descripción puede ser útil para identificar el propósito del Symbol.

const nombre = Symbol('Nombre del símbolo');

En este caso, nombre es un Symbol con una descripción opcional.

La descripción de un símbolo no afecta su unicidad, pero puede ser útil para la depuración.

let simbolo = Symbol('mi simbolo');
console.log(simbolo.toString()); // Imprime: Symbol(mi simbolo)

La descripción se puede obtener a través del método toString() del símbolo.

Unicidad de los Symbols

La principal característica de los símbolos su valor es siempre único y diferente del de todos los demás (incluso si dos símbolos tienen la misma descripción).

let simbolo1 = Symbol('descripcion');
let simbolo2 = Symbol('descripcion');

console.log(simbolo1 === simbolo2); // Imprime: false

En el ejemplo anterior,

  • simbolo1 y simbolo2 son dos símbolos distintos, a pesar de que ambos tienen la misma descripción.
  • Es decir que cada llamada a Symbol() ha producido un identificador único.

Usos del Tipo Symbol

Evitar sobreescritura de propiedades

Uno de los usos más comunes de los Symbols es como claves para las propiedades de objetos, para evitar que sean sobreescritas por accidente.

Vamos a verlo con un ejemplo

let objeto = {
  propiedad: 'valor 1'
};

// Más adelante, otra parte del código añade una propiedad con el mismo nombre:
objeto.propiedad = 'valor 2';

console.log(objeto.propiedad);  // Imprime: 'valor 2'

En este caso,

  • Hemos definido un objeto literal, con la propiedad que valor valor 1
  • Posteriormente, alguien por error, sobreescribe con el valor valor 2
// Creamos un Symbol con una descripción
let simboloPropiedad = Symbol('propiedad');

let objeto = {};

// Usamos el Symbol como clave para la propiedad
objeto[simboloPropiedad] = 'valor 1';

// Más adelante, intentamos añadir otra propiedad con el mismo nombre,
// pero como usamos un Symbol, no hay sobrescritura
let otroSimbolo = Symbol('propiedad');
objeto[otroSimbolo] = 'valor 2';

// Accedemos a las propiedades usando los Symbols
console.log(objeto[simboloPropiedad]);  // Imprime: 'valor 1'
console.log(objeto[otroSimbolo]);       // Imprime: 'valor 2'

En este ejemplo,

  • Creamos un Symbol llamado simboloPropiedad y lo usamos como clave para una propiedad en el objeto objeto.
  • Luego, en otra parte del código, creamos un nuevo Symbol llamado otroSimbolo. Aunque ambos símbolos tienen la misma descripción (‘propiedad’), son diferentes entre sí.
  • Por lo tanto, cuando asignamos 'valor 2' a objeto[otroSimbolo], no sobrescribe el valor de objeto[simboloPropiedad], sino que crea una nueva propiedad.

Métodos y propiedades simbólicas

JavaScript incluye varios símbolos integrados que se usan como claves para métodos y propiedades especiales. Estos símbolos están definidos en el objeto Symbol.

SímboloDescripción
Symbol.iteratorEste símbolo se usa para definir el iterador de un objeto.
Symbol.toStringTagEste símbolo se usa para definir el valor de la propiedad Symbol.toStringTag

Symbol.toStringTag que se usa para personalizar el resultado del método Object.prototype.toString().

Símbolos globales con Symbol.for()

Otro uso diferente de los Symbos ocurre con el método Symbol.for(). Este permite crear un símbolo global que es accesible en todo el entorno de ejecución.

Si intentas crear un símbolo con la misma clave, devolverá el mismo símbolo. Es decir, Symbol.for() lleva una especie de “registro global” de símbolos.

const simboloGlobal1 = Symbol.for('miSimbolo');
const simboloGlobal2 = Symbol.for('miSimbolo');

console.log(simboloGlobal1 === simboloGlobal2); // Imprime: true

En este caso,

  • Creamos un símbolo global con la clave 'miSimbolo' con Symbol.for('miSimbolo').
  • Al llamar nuevamente a Symbol.for('miSimbolo'), JavaScript no crea un nuevo símbolo.
  • En lugar de eso, busca en el registro global de símbolos y, si ya existe un símbolo con esa clave (como 'miSimbolo'), te devuelve el mismo símbolo.
  • Como son el mismo símbolo, la comparación simboloGlobal1 === simboloGlobal2 devuelve true.

Esto es diferente de crear símbolos con Symbol(), que siempre genera un símbolo único, incluso si usas la misma descripción.

En cambio, Symbol.for() asegura que el símbolo creado sea único a nivel global, y si ya existe un símbolo con esa clave, te devolverá el mismo símbolo.

Ejemplos prácticos