L63 - Symbol
🧠 Concepto
Section titled “🧠 Concepto”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).
💻 Crear un Symbol
Section titled “💻 Crear un Symbol”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.
📝 Symbol con objetos
Section titled “📝 Symbol con objetos”const ID = Symbol('id');const usuario = { nombre: 'Ana', [ID]: 12345 // Propiedad con clave Symbol};
console.log(usuario[ID]); // 12345console.log(Object.keys(usuario)); // ['nombre'] ← Symbol NO aparececonsole.log(Object.getOwnPropertyNames(usuario)); // ['nombre']
// Para obtener las propiedades Symbolconsole.log(Object.getOwnPropertySymbols(usuario)); // [Symbol(id)]Propiedades “escondidas”
Section titled “Propiedades “escondidas””Los Symbols permiten añadir propiedades únicas a objetos sin riesgo de colisión:
// Biblioteca Aconst libA = Symbol('libA');usuario[libA] = 'Datos internos de libA';
// Biblioteca Bconst libB = Symbol('libB');usuario[libB] = 'Datos internos de libB';
// Ambas coexisten sin pisarseconsole.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() y Symbol.keyFor()
Section titled “💻 Symbol.for() y Symbol.keyFor()”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 globalconsole.log(Symbol.keyFor(global1)); // 'app.version'⚠️
Symbol.for()NO es lo mismo queSymbol(): 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:
Symbol.iterator
Section titled “Symbol.iterator”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}Symbol.toStringTag
Section titled “Symbol.toStringTag”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]'Symbol.hasInstance
Section titled “Symbol.hasInstance”Personaliza el comportamiento de instanceof:
class Rango { static [Symbol.hasInstance](instancia) { return instancia >= 10 && instancia <= 20; }}
console.log(15 instanceof Rango); // trueconsole.log(5 instanceof Rango); // falseOtros well-known symbols
Section titled “Otros well-known symbols”| Symbol | Uso |
|---|---|
Symbol.toPrimitive | Controla la conversión a primitivo (coerción) |
Symbol.match | Personaliza String.prototype.match() |
Symbol.replace | Personaliza String.prototype.replace() |
Symbol.search | Personaliza String.prototype.search() |
Symbol.split | Personaliza String.prototype.split() |
Symbol.species | Define el constructor para objetos derivados |
Symbol.unscopables | Excluye propiedades de with |
💻 Ejemplo: Symbol.toPrimitive
Section titled “💻 Ejemplo: Symbol.toPrimitive”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); // 25console.log(`${temperatura}`); // '25°C'📝 Metaprogramación con Symbol
Section titled “📝 Metaprogramación con Symbol”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 }⚠️ Limitaciones
Section titled “⚠️ Limitaciones”- 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
Symbolpara evitar colisiones de propiedades en objetos compartidos. UsaSymbol.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.