"El buen diseño es obvio. El gran diseño es transparente"
- Joe Sparano

Symbol en Javascript

5 minutos de lectura
Fecha: 7/4/2015

Hoy vamos a hablar un poco sobre ECMAScript 6, el estandar de Javascript que poco a poco está siendo implementado y que es de esperar sea el futuro cercano de este lenguaje.

Concretamente de Symbol, el nuevo primitivo que se acaba de añadir.

Descripción de la imagen

¿Que son los primitivos?

Primitivos son todos aquellos tipo de datos que tiene este lenguaje con excepción de los Objetos, antes existía 6 tipos de datos que eran los Objetos y los primitivos String, Number, Boolean, Null y Undefined.

Symbol es el nuevo primitivo que se incluye en el ES6.

Hay que puntualizar que de estos primitivos String, Number, Boolean están envueltos en Objetos y eso es algo que podríamos deducir solamente pensando en como operamos con ellos.

Al decir que son envueltos estamos diciendo que al declarar explícitamente o dentro de una variable estos 3 tipos de datos automáticamente ya tenemos ciertos métodos para operar con ellos, y los métodos son propios de los objetos no de los primitivos, ¿verdad que los primitivos Null o Undefined no tienen ningún método?

Dicho esto hay que empezar por decir que Symbol también esta envuelto en un Objeto, por lo que también tiene métodos para operar con él.

¿Como declarar Symbol?

Javascript es un lenguaje que deduce el tipo de datos del propio valor de los mismos, vamos a usar el operador typeof que precisamente sirve para averiguar el tipo de datos para que veáis esto que os cuento.

Primero voy a declarar distintas variables con diferentes valores.

var a = "0";
var b = 0;
var c = false;
var d = null;

Y ahora voy a usar el typeof para preguntar por que tipo de datos son.

console.log(typeof a); // Me devuelve string
console.log(typeof b); // Me devuelve number
console.log(typeof c); // Me devuelve boolean
console.log(typeof d); // Me devuelve null
console.log(typeof e); // Me devuelve undefined

En el caso de las cuatro primeras declaro explícitamente los valores y para undefined simplemente no declaro la variable o la declaras y no le asignas ningún valor que viene a ser lo mismo.

Con Symbol la cosa cambia, para tu declararla tienes que hacerlo de esta manera.

var x = Symbol();
console.log(typeof x); // Me devuelve symbol

Recordáis que como antes decíamos que lo envuelve un Objeto (el objeto Symbol), y que los primitivos a los que también les sucedía esto eran String, Number y Boolean.

A estos los podíamos declarar de estas maneras…

// Declarar un string
var a = "Soy un String";
var b = new String("Soy un String");
var c = String("Soy un String");

Todas las variables contienen el tipo de dato String,

  • En el caso de la variable ‘a’ porque le hemos asignado un literal.
  • La ‘b’ usando el operador new ya que la función global que lo crea es un constructor
  • La ‘c’ llamando directamente a la función global.

En el caso de Symbol

  • No podemos usar una notación literal porque su valor no lo asignamos nosotros,
  • No podemos usar el operador new porque la función global que lo crea no es un constructor
  • Así que la única manera de declararlo es llamando la función global.

Espero que quede claro esto ya que cualquier otra forma de declararlo es imposible.

Para que sirve

Ya sabemos su naturaleza y como declararlos pero la verdadera pregunta es ¿para que nos valen? ya que si no les vemos una utilidad práctica es como si no existieran.

En primer lugar aunque al ver este nombre la traducción mental que rápidamente hacemos es símbolos, en lo que debemos de pensar es que son identificadores y que son identificadores del estilo que lo es un ID en HTML o que es una Primary Key en una base de datos relacional pues los Symbol son únicos y además también son inmutables así que nos podemos ir olvidando de modificar su contenido tras declararlo.

Mirad este ejemplo…

var a = Symbol();
var b = Symbol();
console.log(a === b); // Devuelve false

Con la triple igualdad comprueba que el tipo de dato y su contenido sean iguales, ambos son de tipo Symbol pero obviamente y como decíamos, cada vez que declares uno nuevo será único y por tanto distinto.

Que sea inmutable quiere decir que su contenido no podrá ser modificado por ningún método u operador, aunque como es una variable puedes reasignarla volviendo a declarar su valor.

Dicho esto y pensado en que estamos hablando de ES6 podemos argumentar que para estas cosas ya tenemos las constantes.

Yy es cierto que asignando un literal a una constante no podemos modificarla, pues modificar así es como reasignar.

Pero a una constante podemos asignarle un Objeto y en estos casos si que podemos modificar su contenido, porque modificar un objeto no es reasignar.

Uniendo estos dos conceptos, que las Constantes nunca pueden reasignarse y que los Symbol nunca pueden modificarse y además son únicos, la combinación perfecta para tener un identificador sólido es esta.

const a = Symbol();

¿Y como hacemos para identificar nuestros Symbol? Porque si su valor no lo asignamos nosotros y tampoco lo podemos alterar parece imposible identificarlos. Para ello en el momento en que usamos la función global que lo declara podemos pasar un parámetro que nos sirve de descripción para reconocerlo.

const a = Symbol("Oscar");

De todas formas solo vale para que lo reconozcamos nosotros los Symbol son únicos y si tenemos la feliz idea de declarar dos con la misma descripción lo seguirán siendo y además tampoco tendremos manera de reconocer cual es cual.

const a = Symbol("Oscar");
const b = Symbol("Oscar");
console.log(a === b); // Devuelve false

Símbolos globales

Sí, también existen y no se comportan de la misma manera que los otros, si miras arriba veamos que resultado obtendríamos si los símbolos los hubiéramos declarado como globales, por cierto se haría usando el método Symbol.for

const a = Symbol.for("Oscar");
const b = Symbol.for("Oscar");
console.log(a === b); // Devuelve true

Hay muchos símbolos ya predefinidos y que se usan como identificadores para métodos que usamos a diario, aquí tienes una lista por si tienes curiosidad.

Utilidades

Las utilidades prácticas más usadas de este tipo de datos es la de servir como identificadores para guardad las propiedades de un objeto, ya que usando los símbolos en lugar de escribirlas nosotros a mano evitamos machacar ninguna.