Símbolos ES6

De todas las funciones nuevas de ES6, los símbolos pueden ser una de las más interesantes para mí. Nunca he sido un desarrollador de Ruby, así que nunca he visto ni usado estos...

Introducción

De todas las funciones nuevas de ES6, simbolos podría ser una de las más interesantes para mí. Nunca he sido un desarrollador de Ruby, por lo que nunca he visto ni usado estos tipos primitivos en la práctica. Es un concepto interesante y me sumergiré en lo esencial a lo largo de este artículo.

Símbolos ES6

Entonces, ¿qué es exactamente un símbolo de JavaScript? Es un nuevo tipo de datos primitivo, único e inmutable introducido en ES6, originalmente destinado a proporcionar propiedades privadas.

var sym = Symbol(); 
typeof sym;                         // Returns "symbol" 

Los símbolos se pueden usar para acceder a las propiedades de los objetos, al igual que las cadenas:

var obj = {};
var sym = Symbol();
obj[sym] = "a";
console.log(obj[sym]);              // Prints "a"

La principal diferencia aquí es que la propiedad a la que accede sym no aparece en el objeto si se itera o si stringify'd. Por ejemplo:

var obj = {};
var sym = Symbol();
obj['hi'] = "bye";
obj[sym] = "a";

console.log(obj);                   // Prints "{hi: 'bye'}"

for (var i in obj) {
    console.log(i);                 // Prints "hi"
}

console.log(JSON.stringify(obj));   // Prints {"hi":"bye"}

Entonces, como puede ver, la única forma en que puede acceder a una propiedad "simbólica" es con el objeto de símbolo original, de lo contrario, ni siquiera sabría que la propiedad existe. Entonces, esto significa que podemos usar Símbolos para finalmente tener propiedades privadas en JavaScript, ¿verdad? No. Resulta que los símbolos se degradaron severamente con respecto a la especificación original (por razones que desconozco) y no se pueden usar para crear propiedades privadas de manera confiable. Se puede acceder a los símbolos de un objeto a través de Object.getOwnPropertySymbols, lo que los hace públicos para que todos los vean.

var obj = {};
var sym = Symbol();
obj['hi'] = "bye";
obj[sym] = "a";

Object.getOwnPropertySymbols(obj);  // Returns [ Symbol() ]

Una palabra de advertencia, muchas personas todavía creen que los símbolos JS proporcionan propiedades privadas a los objetos, así que tenga cuidado con lo que lee y cree en los foros y Stack Overflow. Con suerte, los conceptos erróneos se corregirán una vez que ES6 se vuelva más común.

También puede ver muchos ejemplos en los que al símbolo se le pasa una cadena opcional, así:

var sym = Symbol("foo");

Este descriptor se usa estrictamente con fines de depuración y no afecta la unicidad del símbolo. Para hacer esto más claro, aquí hay un ejemplo:

Symbol("foo") === Symbol("foo"); // Evaluates to false

var sym = Symbol("foo");
console.log(sym.toString());        // Prints "Symbol(foo)"

Ámbito global

Es importante darse cuenta de que el uso de la función Symbol() no creará un símbolo global que esté disponible en el ámbito global. El símbolo sigue siendo específico del objeto en el que se utiliza. Sin embargo, puede crear símbolos globales usando Símbolo.para() y Símbolo.keyFor () para obtener y establecer símbolos del registro global de símbolos.

Symbol.for(key) busca símbolos existentes con la clave dada (una cadena) y los devuelve si los encuentra. Si no se encuentra el símbolo, se crea uno nuevo en el registro global con la clave dada y luego se devuelve.

Symbol.for("foo");               // Creates a new global symbol
var sym = Symbol.for("foo");        // Retrieves the already created symbol

A diferencia de Symbol([description]), especificar la clave en Symbol.for(key) devuelve el mismo símbolo cada vez, así que:

Symbol.for("bar") === Symbol.for("bar"); // Evaluates to true
Symbol("bar") === Symbol("bar");            // Evaluates to false

Symbol.keyFor(sym) es esencialmente lo opuesto a Symbol.for(key), en lugar de pasar una clave para obtener un símbolo, pasas un símbolo para obtener una clave.

var sym = Symbol.for("foo");     // Creates new global symbol
console.log(Symbol.keyFor(sym));    // Prints "foo"

Conclusión

Aunque los símbolos de JavaScript son una idea nueva y algo interesante, soy escéptico de su utilidad sin la garantía de propiedades privadas. Algunas personas han sugerido que serán buenos para evitar conflictos de nombres, lo que puede ser útil, pero creo que su verdadero potencial no se realizará sin proporcionar propiedades verdaderamente privadas. Veremos cómo progresan las cosas con futuras actualizaciones.

¿Qué opinas de Símbolos? ¿De qué manera los ha encontrado útiles? ¡Cuéntanos en los comentarios!