Resumen

ES6 introdujo un nuevo tipo de dato primitivo, Symbol, que representa un valor único. Su principal uso es definir nombres de propiedad únicos para objetos.

Además de Number, String, Boolean, Object, null y undefined, ES6 añade el tipo de dato Symbol.


Uso básico

La función Symbol no se puede usar con el comando new, porque Symbol es un tipo de dato primitivo, no un objeto. Puede aceptar una cadena como parámetro para proporcionar una descripción al Symbol recién creado, que se muestra en la consola o cuando se usa como cadena, para facilitar la distinción.

let sy = Symbol("KK"); console.log(sy); // Symbol(KK) typeof(sy); // "symbol" //Con el mismo parámetro, los valores devueltos por Symbol() no son iguales. let sy1 = Symbol("kk"); sy === sy1; // false

Escenarios de uso

Como nombre de propiedad

Uso

Dado que los valores de cada Symbol son diferentes, al usar Symbol como nombre de propiedad de un objeto, se garantiza que los nombres de propiedad no se repitan.

let sy = Symbol("key1"); //Forma 1 let syObject = {}; syObject[sy] = "kk"; console.log(syObject); // {Symbol(key1): "kk"} //Forma 2 let syObject = { [sy]: "kk" }; console.log(syObject); // {Symbol(key1): "kk"} //Forma 3 let syObject = {}; Object.defineProperty(syObject, sy, {value: "kk"}); console.log(syObject); // {Symbol(key1): "kk"}

Cuando Symbol se usa como nombre de propiedad de un objeto, no se puede usar el operador punto, sino corchetes. Porque después del operador punto va una cadena, así que se obtiene la propiedad de cadena 'sy', no la propiedad Symbol 'sy'.

let syObject = {}; syObject[sy] = "kk"; syObject[sy]; // "kk" syObject.sy; // undefined

Puntos a tener en cuenta

Cuando un valor Symbol se usa como nombre de propiedad, dicha propiedad es pública, no privada, y se puede acceder desde fuera de la clase. Sin embargo, no aparecerá en los bucles for...in ni for...of, y no será devuelta por Object.keys() ni Object.getOwnPropertyNames(). Para leer las propiedades Symbol de un objeto, se pueden obtener mediante Object.getOwnPropertySymbols() y Reflect.ownKeys().

let syObject = {}; syObject[sy] = "kk"; console.log(syObject); for (let i in syObject) { console.log(i); } //Sin salida Object.keys(syObject); // [] Object.getOwnPropertySymbols(syObject); // [Symbol(key1)] Reflect.ownKeys(syObject); // [Symbol(key1)]

Definición de constantes

En ES5 se usan cadenas para representar constantes. Por ejemplo:

const COLOR_RED = "red";
const COLOR_YELLOW = "yellow";
const COLOR_BLUE = "blue";

Pero usar cadenas no garantiza que las constantes sean únicas, lo que puede causar algunos problemas:

const COLOR_RED = "red"; const COLOR_YELLOW = "yellow"; const COLOR_BLUE = "blue"; const MY_BLUE = "blue"; function ColorException(message) { this.message = message; this.name = "ColorException"; } function getConstantName(color) { switch (color) { case COLOR_RED : return "COLOR_RED"; case COLOR_YELLOW : return "COLOR_YELLOW "; case COLOR_BLUE: return "COLOR_BLUE"; case MY_BLUE: return "MY_BLUE"; default: throw new ColorException("Can't find this color"); } } try { var color = "green"; //green provoca una excepción var colorName = getConstantName(color); } catch (e) { var colorName = "unknown"; console.log(e.message, e.name); //Pasar el objeto de excepción al manejador de errores }

Pero al usar Symbol para definir constantes, se puede garantizar que los valores de este grupo de constantes no sean iguales. Usa Symbol para modificar el ejemplo anterior.

const COLOR_RED = Symbol("red"); const COLOR_YELLOW = Symbol("yellow"); const COLOR_BLUE = Symbol("blue"); function ColorException(message) { this.message = message; this.name = "ColorException"; } function getConstantName(color) { switch (color) { case COLOR_RED : return "COLOR_RED"; case COLOR_YELLOW : return "COLOR_YELLOW "; case COLOR_BLUE: return "COLOR_BLUE"; default: throw new ColorException("Can't find this color"); } } try { var color = "green"; //green provoca una excepción var colorName = getConstantName(color); } catch (e) { var colorName = "unknown"; console.log(e.message, e.name); //Pasar el objeto de excepción al manejador de errores }

El valor de Symbol es único, por lo que no aparecerán constantes con el mismo valor; así se garantiza que switch se ejecute de la manera prevista en el código.

Symbol.for()

Symbol.for() es similar al patrón singleton. Primero busca globalmente entre los Symbol registrados si existe un valor Symbol con ese parámetro de cadena como nombre. Si existe, devuelve ese valor Symbol; si no, crea y devuelve un nuevo valor Symbol con ese parámetro de cadena como nombre, y lo registra en el entorno global para su búsqueda.

let yellow = Symbol("Yellow"); let yellow1 = Symbol.for("Yellow"); yellow === yellow1; // false let yellow2 = Symbol.for("Yellow"); yellow1 === yellow2; // true

Symbol.keyFor()

Symbol.keyFor() devuelve la clave de un valor Symbol ya registrado, para verificar si el valor Symbol con ese parámetro de cadena como nombre ha sido registrado.

let yellow1 = Symbol.for("Yellow"); Symbol.keyFor(yellow1); // "Yellow"