Skip to content

L63 - Symbol

Symbol es un tipo de dato primitivo introducido en ES6 que representa un valor único e inmutable. Se usa principalmente para crear propiedades de objetos con clave única (evitando colisiones) y para metaprogramación a través de símbolos bien conocidos (well-known symbols).

const sim1 = Symbol();
const sim2 = Symbol();
console.log(sim1 === sim2); // false (cada Symbol es único)
// Con descripción (útil para depuración)
const sim3 = Symbol('miDescripcion');
console.log(sim3.toString()); // 'Symbol(miDescripcion)'

⚠️ La descripción es solo una etiqueta, no afecta a la unicidad.

const ID = Symbol('id');
const usuario = {
nombre: 'Ana',
[ID]: 12345 // Propiedad con clave Symbol
};
console.log(usuario[ID]); // 12345
console.log(Object.keys(usuario)); // ['nombre'] ← Symbol NO aparece
console.log(Object.getOwnPropertyNames(usuario)); // ['nombre']
// Para obtener las propiedades Symbol
console.log(Object.getOwnPropertySymbols(usuario)); // [Symbol(id)]

Los Symbols permiten añadir propiedades únicas a objetos sin riesgo de colisión:

// Biblioteca A
const libA = Symbol('libA');
usuario[libA] = 'Datos internos de libA';
// Biblioteca B
const libB = Symbol('libB');
usuario[libB] = 'Datos internos de libB';
// Ambas coexisten sin pisarse
console.log(usuario[libA]); // 'Datos internos de libA'
console.log(usuario[libB]); // 'Datos internos de libB'

No hay riesgo de que un for...in o Object.keys() las exponga accidentalmente.

Symbol.for(clave) crea o recupera un símbolo compartido globalmente (registro global de símbolos):

const global1 = Symbol.for('app.version');
const global2 = Symbol.for('app.version');
console.log(global1 === global2); // true (misma clave = mismo Symbol)
// Obtener la clave de un Symbol global
console.log(Symbol.keyFor(global1)); // 'app.version'

⚠️ Symbol.for() NO es lo mismo que Symbol(): el primero busca en el registro global, el segundo siempre crea uno nuevo.

🧠 Well-known Symbols (Metaprogramación)

Section titled “🧠 Well-known Symbols (Metaprogramación)”

JavaScript tiene símbolos predefinidos que permiten personalizar el comportamiento de los objetos:

Hace que un objeto sea iterable (compatible con for...of):

const coleccion = {
datos: [10, 20, 30],
[Symbol.iterator]() {
let i = 0;
const datos = this.datos;
return {
next() {
if (i < datos.length) {
return { value: datos[i++] * 2, done: false };
}
return { value: undefined, done: true };
}
};
}
};
for (const valor of coleccion) {
console.log(valor); // 20, 40, 60
}

Personaliza la salida de Object.prototype.toString():

class MiClase {
get [Symbol.toStringTag]() {
return 'MiClasePersonalizada';
}
}
const obj = new MiClase();
console.log(Object.prototype.toString.call(obj)); // '[object MiClasePersonalizada]'

Personaliza el comportamiento de instanceof:

class Rango {
static [Symbol.hasInstance](instancia) {
return instancia >= 10 && instancia <= 20;
}
}
console.log(15 instanceof Rango); // true
console.log(5 instanceof Rango); // false
SymbolUso
Symbol.toPrimitiveControla la conversión a primitivo (coerción)
Symbol.matchPersonaliza String.prototype.match()
Symbol.replacePersonaliza String.prototype.replace()
Symbol.searchPersonaliza String.prototype.search()
Symbol.splitPersonaliza String.prototype.split()
Symbol.speciesDefine el constructor para objetos derivados
Symbol.unscopablesExcluye propiedades de with
const temperatura = {
valor: 25,
unidad: '°C',
[Symbol.toPrimitive](tipo) {
if (tipo === 'string') return `${this.valor}${this.unidad}`;
if (tipo === 'number') return this.valor;
return this.valor.toString();
}
};
console.log(String(temperatura)); // '25°C'
console.log(+temperatura); // 25
console.log(`${temperatura}`); // '25°C'

La metaprogramación es código que escribe o manipula otro código. Los Symbols son una herramienta clave porque permiten extender el comportamiento de objetos desde fuera:

function definirMetadatos(objeto, metadatos) {
const meta = Symbol('metadata');
objeto[meta] = metadatos;
return {
getMetadata() { return objeto[meta]; },
setMetadata(datos) { objeto[meta] = datos; }
};
}
const usuario = { nombre: 'Ana' };
const metadata = definirMetadatos(usuario, { creado: Date.now() });
console.log(metadata.getMetadata()); // { creado: 1678900000000 }
  • Los Symbols no son totalmente privados: se pueden descubrir con Object.getOwnPropertySymbols().
  • No se serializan en JSON: JSON.stringify() omite propiedades con clave Symbol.
  • No son compatibles con for...in: las propiedades Symbol no aparecen en iteraciones.

🎯 Regla de oro: usa Symbol para evitar colisiones de propiedades en objetos compartidos. Usa Symbol.for() para símbolos globales que deben ser accesibles desde diferentes módulos. Aplica well-known symbols para personalizar el comportamiento interno de tus objetos.