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 conJSON.stringify
se eliminarán todos los pares inicializados con un Símbolo como clave.
La ejecución deObject.keys
tampoco devolverá dichos paresSymbol()->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.