tutz

Tipo de dato Symbol en JavaScript

En ECMAScript 6 se agrego un nuevo tipo de dato llamado Symbol. Los simbolos son valores primitivos, inmutables y cada instancia es única.

El proposito de este tipo de dato es garantizar identificadores únicos para las propiedades de los objetos, y de esta manera no tener el riesgo de colisión de propiedades.

Uso

Los simbolos son instanciados usando la función Symbol(). Si usamos el operador typeof con un símbolo entonces nos retornará symbol.

const symbolExample = Symbol();
console.log(typeof symbolExample); // symbol

Cuando invocamos la función Symbol, podemos pasarle una cadena que será usada para identificar la instancia del símbolo. Pero igual debemos de tomar en cuenta por mas que le pasemos la misma cadena a la función, al final cada instancia será diferente.

const symbolOne = Symbol();
const symbolTwo = Symbol();

console.log(symbolOne === symbolTwo); // false

const nameSymbol = Symbol('name');
const otherNameSymbol = Symbol('name');

console.log(nameSymbol === otherNameSymbol); // false

Es importante destacar que la función Symbol no se puede utilizar con la keyword new. El proposito de esto es para evitar symbol object wrappers, como es posible con Boolean, String, y Number que admiten el comportamiento de constructor y crean una instancia de un primitive wrapper object.

const anyBoolean = new Boolean();
console.log(typeof anyBoolean); // object

const anyString = new String();
console.log(typeof anyString); // object

const anyNumber = new Number();
console.log(typeof anyNumber); // object

const anySymbol = new Symbol(); // TypeError: Symbol is not a constructor

Usando el Registro Global de Simbolos

En escenarios en donde diferentes partes del runtime podrian querer compartir o reusar una instancia de symbol, es posible crear y reusar simbolos usando una cadena como clave del registro global de simbolos.

Symbol.for()

Esto puede ser logrado usando Symbol.for().

const ageGlobalSymbol = Symbol.for('age');

Symbol.for() es una operación idempotente para cada cadena clave. La primera vez es llamada con la cada dada, esto revisará el registro global de simbolos, si no existe ningún símbolo, entonces genera una nueva instancia de símbolo y lo agrega al registro.

Si se invoca nuevamente la función con la misma cadena, entonces revisara el registro global de simbolos y como ya tenemos uno con esa clave, entonces devolverá ese que hemos creado.

const cityGlobalSymbol = Symbol.for('city');
const otherCityGlobalSymbol = Symbol.for('city');

console.log(cityGlobalSymbol === otherCityGlobalSymbol); // true

Los simbolos definidos en el registro global son totalmente distintos de los simbolos creados usando Symbol(), aún si le pasamos la misma cadena.

const localSymbol = Symbol('a');
const globalSymbol = Symbol.for('a');

console.log(localSymbol === globalSymbol); // false

Symbol.keyFor()

Es posible obtener la cadena que le hemos pasado como clave al símbolo global. Para esto usamos la función Symbol.keyFor().

const symbolB = Symbol.for('b');
console.log(Symbol.keyFor(symbolB)); // b

Si no le pasas un símbolo a Symbol.keyFor() entonces te retornará un error.

Symbol.keyFor(666); // TypeError: 666 is not a symbol

Usando simbolos como propiedades

En cualquier lugar donde puedas usar una cadena o número como propiedad, tu tambien puedes usar un símbolo. Esto incluye a propiedades de objetos literales, Object.defineProperty() y Object.defineProperties().

Un objeto literal solo puede usar un símbolo como propiedad dentro de la sintaxis de propiedad calculada.

const p1 = Symbol('abc'),
  p2 = Symbol('def'),
  p3 = Symbol('ghi'),
  p4 = Symbol('jkl'),
  p5 = Symbol('mno');

let objectExample = {
  [p1]: 'abc',
};
objectExample[p2] = 'def';

Object.defineProperty(objectExample, p3, { value: 'ghi' });
Object.defineProperties(objectExample, {
  [p4]: { value: 'jkl' },
  [p5]: { value: 'mno' },
});

console.log(objectExample);
// {Symbol(abc): "abc", Symbol(def): "def", Symbol(ghi): "ghi", Symbol(jkl): "jkl", Symbol(mno): "mno"}

Y esto es todo lo básico que podemos aprender sobre el tipo de dato Symbol en JavaScript. En otros artículos puedes leer temas más profuncos sobre este tipo de dato.