ACTUALIZACIÓN : Recientemente apareció un artículo brillante de Mozilla . Léelo si tienes curiosidad.
Como ya sabrán, planean incluir un nuevo tipo de Símbolo primitivo en ECMAScript 6 (sin mencionar algunas otras cosas locas). Siempre pensé que la :symbol
noción en Ruby es innecesaria; podríamos usar fácilmente cadenas simples, 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?
private
ypublic
palabras clave de atributos de clase que decidieron deshacerse de implementación de la clase más simple. En lugar dethis.x = x
que se suponía que debías hacerpublic x = x
y para variables privadasprivate y = y
. Decidieron deshacerse de eso para una implementación de clase mucho más mínima. Symbol sería una solución alternativa necesaria para obtener propiedades privadas en la implementación mínima.Respuestas:
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, usando
Object.getOwnPropertySymbols
o proxies.Ahora se conocen como símbolos únicos y su único uso previsto es evitar conflictos de nombres entre propiedades. Por ejemplo, el propio ECMAScript ahora puede introducir ganchos de extensión a través de ciertos métodos que puede colocar en objetos (por ejemplo, para definir su protocolo de iteración) sin arriesgarlos a chocar con los nombres de usuario.
Es discutible si eso es lo suficientemente fuerte como una motivación para agregar símbolos al idioma.
fuente
Object.getOwnPropertySymbols
no es la única fuga; la más difícil es la capacidad de usar servidores proxy para interceptar el acceso a una propiedad "privada".Los símbolos no garantizan la verdadera privacidad, pero pueden usarse 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.
Arriba, la
Pet
propiedad de la clasetype
no es privada. Para hacerlo privado, tenemos que crear un cierre. El siguiente ejemplo ilustra cómo podemos hacertype
privado el uso de un cierre.Desventaja del enfoque anterior: Estamos introduciendo un cierre adicional para cada
Pet
instancia creada, lo que puede dañar el rendimiento.Ahora te presentamos
Symbol
. Esto puede ayudarnos a hacer que una propiedad sea privada sin usar cierres innecesarios adicionales. Ejemplo de código a continuación:fuente
_
no garantiza una verdadera privacidad, pero puede usarse para separar las propiedades públicas e internas de los objetos. En otras palabras, respuesta inútil.Symbols
son un tipo de objeto nuevo y especial que se puede usar como un nombre de propiedad único en los objetos. Usar enSymbol
lugar destring
's permite que diferentes módulos creen propiedades que no entren en conflicto entre sí.Symbols
también se puede hacer privado, de modo que cualquiera que aún no tenga acceso directo a la propiedad no pueda acceder a sus propiedadesSymbol
.Symbols
Son una nueva primitiva . Al igual que elnumber
,string
yboolean
primitivas,Symbol
tienen una función que puede ser utilizado para crearlos. A diferencia de las otras primitivas,Symbols
no tienen una sintaxis literal (por ejemplo, cómostring
tiene''
) - la única manera de crear ellos es elSymbol
constructor de la siguiente manera:En realidad,
Symbol
son solo una forma ligeramente diferente de adjuntar propiedades a un objeto: podría proporcionar fácilmente losSymbols
métodos conocidos como estándar, tal comoObject.prototype.hasOwnProperty
aparece en todo lo que heredaObject
.Estos son algunos de los beneficios del
Symbol
tipo primitivo.Symbols
tener depurabilidad incorporadaSymbols
se puede dar una descripción, que en realidad solo se usa para la depuración para hacer la vida un poco más fácil al iniciar sesión en una consola.Symbols
puede usarse comoObject
llavesAquí es donde se
Symbol
pone realmente interesante. Están fuertemente entrelazados con objetos.Symbol
puede asignarse como claves a objetos, lo que significa que puede asignar un número ilimitado de objetos únicosSymbol
a un objeto y garantizar que nunca entren en conflicto con lasstring
teclas u otros objetos únicosSymbols
.Symbols
se puede usar como un valor único.Supongamos que usted tiene una biblioteca de registro, que incluye múltiples niveles de registro, tales como
logger.levels.DEBUG
,logger.levels.INFO
,logger.levels.WARN
y así sucesivamente. En el código ES5 le gustaría hacer estosstring
s (sologger.levels.DEBUG === 'debug'
) onumber
s (logger.levels.DEBUG === 10
). Ambos no son ideales ya que esos valores no son valores únicos, ¡pero sí loSymbol
son! Entonceslogger.levels
simplemente se convierte en:Lea más en este gran artículo .
fuente
log.levels = {DEBUG: Symbol('debug')
y no simplementelog.levels = {DEBUG:'debug'}
. Al final es lo mismo. Creo que vale la pena mencionar que los símbolos son invisibles al iterar sobre las teclas de un objeto. esa es su "cosa"{}
y lograr el mismo resultado (como valor único), o tal vez se prefiere un literal en ese proyecto, o puede decir que uno necesita leer el documento primero.) I personalmente creo que proporciona una buena legibilidad de significado único en el códigoSymbol("some message")
convierte en un{message:'some message'}
objeto posiblemente mejor aquí, ya que puede agregar múltiples campos.Esta publicación trata sobre el
Symbol()
, suministrado con ejemplos reales que pude encontrar / hacer y hechos 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 solo el tipo de datos en JavaScript que no tiene literal
cualquier variable, definida con
Symbol()
, obtiene contenido único, pero no es realmente privado .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 depurable
Puedes hacerlo de esta manera:
O de esta manera:
La
"some text here"
cadena no se puede extraer del símbolo, es solo una descripción para fines de depuración. No cambia el comportamiento del símbolo de ninguna manera. Aunque, podríaconsole.log
hacerlo (lo cual es justo, ya que el valor es para la depuración, para no confundir ese registro con alguna otra entrada de registro):2. Para obtener un símbolo para algunos datos de cadena
En este caso, el valor del símbolo se tiene realmente en cuenta y de esta manera dos símbolos pueden no ser únicos.
Llamemos a esos símbolos símbolos de "segundo tipo". No se cruzan con los símbolos de "primer tipo" (es decir, los definidos con
Symbol(data)
) de ninguna manera.Los siguientes dos párrafos pertenecen solo al símbolo de primer tipo .
¿Cómo me beneficio al usar Symbol en lugar de los tipos de datos más antiguos?
Primero consideremos un objeto, un tipo de datos estándar. Podríamos definir algunos pares clave-valor allí y tener acceso a los valores especificando la clave.
¿Qué pasa si tenemos dos personas con el nombre de Peter?
Haciendo esto:
No tendría mucho sentido.
Entonces, parece ser un problema de dos personas absolutamente diferentes que tienen el mismo nombre. Entonces veamos nuevo
Symbol()
. Es como una persona en la vida real: cualquier persona es única , pero sus nombres pueden ser iguales. Definamos dos "personas".Ahora tenemos dos personas diferentes con el mismo nombre. ¿Son nuestras personas realmente diferentes? Son; puedes verificar esto:
¿Cómo nos beneficiamos allí?
Podemos hacer dos entradas en su objeto para las diferentes personas y no pueden confundirse de ninguna manera.
Usando esta inicialización, es absolutamente imposible confundir las entradas para la primera y la segunda persona. Llamar
console.log
a ellos mostrará correctamente sus segundos nombres.Cuando se usa en un objeto, ¿cómo es diferente en comparación con la definición de propiedad no enumerable?
De hecho, ya existía una forma de definir una propiedad para ocultar
Object.keys
y enumerar. Aquí está:¿Qué diferencia
Symbol()
trae allí? La diferencia es que aún puede obtener la propiedad definidaObject.defineProperty
de la manera habitual:Y si se define con Symbol como en el párrafo anterior:
Tendrá la capacidad de recibir su valor solo si conoce su variable, es decir
Además, definir otra propiedad bajo la clave
"apple"
hará que el objeto descarte la anterior (y si está codificada, podría arrojar un error). Entonces, ¡no más manzanas! Eso es una lástima. Al referirse al párrafo anterior, los Símbolos son únicos y definen una clave queSymbol()
lo hará único.Conversión de tipo y verificación
A diferencia de otros tipos de datos, es imposible convertirlos
Symbol()
a cualquier otro tipo de datos.Es posible "hacer" un símbolo basado en un tipo de datos primitivo llamando
Symbol(data)
.En términos de verificar el tipo, nada cambia.
fuente
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 ().
Aunque dado un objeto per se, tales propiedades aún 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 algunos métodos directos, que a veces pueden ser suficientes desde una perspectiva OOP.
fuente
Un símbolo JS es un nuevo tipo de datos primitivos. Son tokens que sirven como identificaciones únicas . Se puede crear un símbolo usando el
Symbol
constructor. Tomemos, por ejemplo, este fragmento de MDN:A menudo es útil usar símbolos como claves de propiedad de objeto únicas, por ejemplo:
fuente
Fuente
fuente