libro español es6 ecmascript javascript symbols ecmascript-harmony ecmascript-6

javascript - es6 - ecmascript 7 pdf español



¿Cuál es la motivación para llevar los símbolos a ES6? (5)

Así es como lo veo. Los símbolos proporcionan "un nivel adicional de privacidad", al evitar que las claves / propiedades de un objeto se expongan a través de algunos métodos populares como Object.keys () y JSON.stringify ().

var age = Symbol(); // declared in another module perhaps? class Person { constructor(n,a){ this.name = n; this[age] = a; } introduce(){ console.log(`My name is ${this.name}. I am ${this[age]-10}.`); } } var j = new Person(''Jane'',45); j.introduce(); // My name is Jane. I am 35. console.log(JSON.stringify(j)); // {"name":"Jane"} console.log(Object.keys(j)); // ["name"] console.log(j[age]); // 45 (well…only if you know the age in the first place…)

Aunque dado un objeto en sí, dichas propiedades todavía pueden exponerse a través de la reflexión, el proxy, Object.getOwnPropertySymbols (), etc., no hay medios naturales para acceder a ellos a través de unos pocos métodos directos, que pueden ser suficientes a veces desde una perspectiva de POO.

ACTUALIZACIÓN : Recientemente surgió un brillante artículo de Mozilla . Léelo si tienes curiosidad.

Como sabrán, planean incluir un nuevo tipo de símbolo primitivo en ECMAScript 6 (sin mencionar algunas otras locuras). Siempre pensé que la noción de :symbol en Ruby es innecesaria; Podríamos usar cadenas simples en su lugar, como lo hacemos en JavaScript. Y ahora deciden complicar las cosas en JS con eso.

No entiendo la motivación. ¿Podría alguien explicarme si realmente necesitamos símbolos en JavaScript?


Esta publicación es sobre el Symbol() , que se suministra con ejemplos reales que pude encontrar / hacer y datos y definiciones que pude encontrar.

TLDR;

El Symbol() es el tipo de datos, introducido con el lanzamiento de ECMAScript 6 (ES6).

Hay dos hechos curiosos sobre el Símbolo.

  • El primer tipo de datos y el único tipo de datos en JavaScript que no tiene literal

  • cualquier variable, definida con Symbol() , obtiene contenido único, pero no es realmente share .

  • cualquier dato tiene su propio símbolo, y para los mismos datos los símbolos serían los mismos . Más información en el siguiente párrafo, de lo contrario no es un TLRD; :)

¿Cómo inicializo el símbolo?

1. Para obtener un identificador único con un valor de depuración

Puedes hacerlo de esta manera:

var mySymbol1 = Symbol();

O de esta manera:

var mySymbol2 = Symbol("some text here");

La cadena "some text here" no se puede extraer del símbolo, es solo una descripción para propósitos de depuración. No cambia el comportamiento del símbolo de ninguna manera. Sin embargo, podría console.log (lo que es justo, ya que el valor es para la depuración, para no confundir ese registro con otra entrada de registro):

console.log(mySymbol2); // Symbol(some text here)

2. Para obtener un símbolo para algunos datos de cadena.

En este caso, el valor del símbolo se toma en cuenta y, de esta manera, dos símbolos pueden no ser únicos.

var a1 = Symbol.for("test"); var a2 = Symbol.for("test"); console.log(a1 == a2); //true!

Llamemos a esos símbolos símbolos de "segundo tipo". No se intersectan con los símbolos del "primer tipo" (es decir, los definidos con el Symbol(data) ) de ninguna manera.

Los siguientes dos párrafos pertenecen únicamente al primer símbolo de tipo .

¿Cómo puedo beneficiarme del uso de Symbol en lugar de los tipos de datos anteriores?

Consideremos primero un objeto, un tipo de datos estándar. Podríamos definir algunos pares clave-valores allí y tener acceso a los valores especificando la clave.

var persons = {"peter":"pan","jon":"doe"}; console.log(persons.peter); // pan

¿Y si tenemos dos personas con el nombre de Pedro?

Haciendo esto:

var persons = {"peter":"first", "peter":"pan"};

no tendría mucho sentido

Entonces, parece ser un problema de dos personas absolutamente diferentes que tienen un mismo nombre. A continuación, vamos a referir nuevo Symbol() . Es como una persona en la vida real: cualquier persona es única , pero sus nombres pueden ser iguales. Definamos dos "personas".

var a = Symbol("peter"); var b = Symbol("peter");

Ahora tenemos dos personas diferentes con el mismo nombre. ¿Son nuestras personas realmente diferentes? Son; puedes comprobar esto:

console.log(a == b); // false

¿Cómo nos beneficiamos allí?

Podemos hacer dos entradas en su objeto para las diferentes personas y no se pueden confundir de ninguna manera.

var firstPerson = Symbol("peter"); var secondPerson = Symbol("peter"); var persons = {[firstPerson]:"first", [secondPerson]:"pan"};

Nota:
Vale la pena notar, sin embargo, que al clasificar el objeto con JSON.stringify se eliminarán todos los pares inicializados con un Símbolo como clave.
La ejecución de Object.keys tampoco devolverá dichos pares Symbol()->value .

Usando esta inicialización, es absolutamente imposible confundir las entradas con la primera y la segunda persona. Llamar a console.log para ellos dará salida correctamente a sus segundos nombres.

console.log(persons[a]); // first console.log(persons[b]); // pan

Cuando se utiliza en el objeto, ¿en qué se diferencia en comparación con la definición de propiedad no enumerable?

De hecho, ya existía una forma de definir una propiedad que se oculta de Object.keys y la enumeración. Aquí está:

var anObject = {}; var fruit = "apple"; Object.defineProperty( anObject, fruit, { enumerable: false, value: "green" });

¿Qué diferencia trae el Symbol() ? La diferencia es que aún puede obtener la propiedad definida con Object.defineProperty de la forma habitual:

console.log(anObject[fruit]); //green console.log(anObject["apple"]); //green console.log(anObject.apple); //green

Y si se define con el símbolo como en el párrafo anterior:

fruit = Symbol("apple");

Tendrá la capacidad de recibir su valor solo si conoce su variable, es decir,

console.log(anObject[fruit]); //green console.log(anObject["apple"]); //undefined console.log(anObject.apple); //undefined

Además, la definición de otra propiedad bajo la tecla "apple" hará que el objeto elimine la anterior (y si está codificado, podría generar un error). Así que, ¡no más manzanas! Eso es una lástima. Refiriéndose al párrafo anterior, los Símbolos son únicos y la definición de una clave como Symbol() lo hará único.

Tipo de conversión y comprobación

  • A diferencia de otros tipos de datos, es imposible convertir el Symbol() a cualquier otro tipo de datos.

  • Es posible "hacer" un símbolo basado en un tipo de datos primitivo llamando a Symbol(data) .

  • En cuanto a la comprobación del tipo, nada cambia.

    function isSymbol ( variable ) { return typeof someSymbol === "symbol"; } var a_Symbol = Symbol("hey!"); var totally_Not_A_Symbol = "hey"; console.log(isSymbol(a_Symbol)); //true console.log(isSymbol(totally_Not_A_Symbol)); //false


La motivación original para introducir símbolos en Javascript era habilitar propiedades privadas .

Desafortunadamente, terminaron siendo severamente degradados. Ya no son privados, ya que puede encontrarlos a través de la reflexión, por ejemplo, utilizando Object.getOwnPropertySymbols o proxies.

Ahora se conocen como símbolos únicos y su único uso previsto es evitar choques de nombres entre propiedades. Por ejemplo, el propio ECMAScript ahora puede introducir enganches de extensión a través de ciertos métodos que puede poner en objetos (por ejemplo, para definir su protocolo de iteración) sin el riesgo de que entren en conflicto con los nombres de usuario.

Si eso es lo suficientemente fuerte como una motivación para agregar símbolos al lenguaje es discutible.


Los símbolos no garantizan una verdadera privacidad, pero se pueden utilizar para separar las propiedades públicas e internas de los objetos. Tomemos un ejemplo donde podemos usar Symbol para tener propiedades privadas.

Tomemos un ejemplo donde una propiedad de un objeto no es privada.

var Pet = (function() { function Pet(type) { this.type = type; } Pet.prototype.getType = function() { return this.type; } return Pet; }()); var a = new Pet(''dog''); console.log(a.getType());//Output: dog a.type = null; //Modified outside console.log(a.getType());//Output: null

Arriba, el type propiedad de la clase Pet no es privado. Para hacerlo privado tenemos que crear un cierre. El siguiente ejemplo ilustra cómo podemos hacer que el type privado usando un cierre.

var Pet = (function() { function Pet(type) { this.getType = function(){ return type; }; } return Pet; }()); var b = new Pet(''dog''); console.log(b.getType());//dog b.type = null; //Stays private console.log(b.getType());//dog

Desventaja del enfoque anterior: estamos introduciendo un cierre adicional para cada instancia de Pet creada, lo que puede dañar el rendimiento.

Ahora introducimos el Symbol . Esto puede ayudarnos a hacer una propiedad privada sin utilizar cierres innecesarios adicionales. Código de ejemplo a continuación:

var Pet = (function() { var typeSymbol = Symbol(''type''); function Pet(type) { this[typeSymbol] = type; } Pet.prototype.getType = function(){ return this[typeSymbol]; } return Pet; }()); var a = new Pet(''dog''); console.log(a.getType());//Output: dog a.type = null; //Stays private console.log(a.getType());//Output: dog


Symbols son un nuevo tipo de objeto especial que se puede usar como un nombre de propiedad único en los objetos. El uso de Symbol lugar de las string permite que diferentes módulos creen propiedades que no entren en conflicto entre sí. Symbols también pueden hacerse privados, por lo que no se puede acceder a sus propiedades por alguien que aún no tenga acceso directo al Symbol .

Symbols son una nueva primitiva . Al igual que el number , la string y los primitivos boolean , Symbol tiene una función que se puede usar para crearlos. A diferencia de las otras primitivas, los Symbols no tienen una sintaxis literal (por ejemplo, cómo tiene la string '''' ): la única forma de crearlos es con el constructor de Symbol de la siguiente manera:

let symbol = Symbol();

En realidad, los Symbol son solo una forma ligeramente diferente de adjuntar propiedades a un objeto: puede proporcionar fácilmente los Symbols conocidos como métodos estándar, como Object.prototype.hasOwnProperty que aparece en todo lo que hereda de Object .

Éstos son algunos de los beneficios del tipo primitivo Symbol .

Symbols tienen debugability incorporado

Symbols se les puede dar una descripción, que en realidad se usa solo para la depuración para hacer la vida un poco más fácil cuando se registran en una consola.

Symbols se pueden utilizar como claves de Object

Aquí es donde los Symbol ponen realmente interesantes. Están fuertemente entrelazados con objetos. Symbol puede asignarse como claves a objetos, lo que significa que puede asignar un número ilimitado de Symbol únicos a un objeto y garantizar que nunca entrarán en conflicto con claves de string u otros Symbols únicos.

Symbols se pueden utilizar como un valor único.

Supongamos que tiene una biblioteca de registro, que incluye varios niveles de registro como logger.levels.DEBUG , logger.levels.INFO , logger.levels.WARN y así sucesivamente. En el código ES5 desea hacer estas string s (así que logger.levels.DEBUG === ''debug'' ), o el number s ( logger.levels.DEBUG === 10 ). Ambos no son ideales, ya que esos valores no son valores únicos, ¡pero los Symbol son! Así logger.levels simplemente se convierte en:

log.levels = { DEBUG: Symbol(''debug''), INFO: Symbol(''info''), WARN: Symbol(''warn''), }; log(log.levels.DEBUG, ''debug message''); log(log.levels.INFO, ''info message'');

Lea más en este gran artículo.