Seleccionar página
Cuando se conocen las clases en ECMAScript 2015 (ES6) se echan en falta algunos mecanismos para definir propiedades o métodos ocultos, pudiendo de esta forma proteger estos miembros de miradas curiosas. Es algo común en muchos lenguajes con orientación a objetos y parecía una carencia importante en Javascript.

Rápidamente se plantearon varias alternativas para la encapsulación en las clases de ES6, una de ellas está basada en el uso de Symbol, ya que un objeto puede contener propiedades cuya clave es un símbolo en vez de una cadena de texto. La idea es que, si sólo nosotros tenemos acceso al símbolo con el que se ha creado el miembro, sólo nosotros podremos acceder al miembro del objeto.

Más o menos, esto es un ejemplo de lo que se plantea el uso de Symbol para dar protección a ciertos miembros del objeto:

const SECRET = Symbol( 'SECRET' );

class A {
  constructor ( data ) {
    this[ SECRET ] = data;
  }
}

const a = new A( 'no se lo digas a nadie' );

No sólo se puede utilizar para propiedades, también podemos definir métodos por medio de Symbol y algo de destructuring, por ejemplo:

const HIDE = Symbol( 'HIDE' );

class B {
  [ HIDE ] () {
    return 'oculto';
  }
}

const b = new B( );
console.log( b[ HIDE ]() );

Sólo si se tiene acceso a las constantes con los símbolos se puede acceder a los miembros creados con SECRET y HIDE. Si mantenemos estas constantes como locales al módulo o dentro de una closure, todo parece bastante prometedor.

Rápidamente vimos que los depuradores de los navegadores y de entornos integrados mostraban los miembros definidos con Symbol(). Fue una decepción, pero no era un drama, al fin y al cabo, desde un entorno de depuración es posible detener la ejecución en cualquier punto y comprobar el contenido de una variable local, por lo que parece imposible protegerse de este tipo de herramientas.

Symbol en el depurador

Llegamos a este punto, lo que no nos habíamos dado cuenta es que hay varias formas de obtener desde un programa el Symbol con el que se ha definido el miembro del objeto y por lo tanto, acceder sin problemas y sin limitaciones a estas propiedades que se intentó ocultar, pero que son perfectamente visibles con un poco de esfuerzo.

Un simple código como nos permite obtener el contenido de todas las propiedades, incluido las definidas con símbolos.

console.log( Object.getOwnPropertyDescriptors(a) )

Lo que ya fue el colmo de los males es descubrir que Object.getOwnPropertySymbols() o Reflect.ownKeys() devuelven una matriz que incluyen los símbolos utilizados en el objeto y que permite a un programa acceder sin problemas a estas propiedades.

const SECRET = Symbol( 'SECRET' );

class A {
  constructor ( data ) {
    this[ SECRET ] = data;
  }
}

const a = new A( 'no se lo digas a nadie' );

const MySYMBOL = Object.getOwnPropertySymbols( a )[ 0 ];
a[MySYMBOL] = 'todo el mundo lo sabe';

Es cierto que los símbolos son ignorados en muchas ocasiones, por ejemplo, por los bucles for...in y por métodos habituales para obtener los nombres de las propiedades, Object.keys() y Object.getOwnPropertyNames(), por lo que las propiedades creados con ellos no son tan visibles como el resto.

En un futuro próximo parece que el estándar de Javascript va a incluir una forma de definir miembros privados (ver la propuesta de Private instance methods and accessors). Esta propuesta está en estado 3 (de un total de 4) y se espera que próximamente sea incluida de forma efectiva en los motores de Javascript.

Por lo tanto, los Symbol tienen muchas utilidades, pero no consiguen una ocultación efectiva de los miembros de un objeto. Es verdad que las propiedades creadas con Symbol son más complicadas de acceder, pero desde luego no son privadas.

Novedades

Template a fondo

Hay dos formas estándar de crear contenido en un componente de forma flexible: la etiqueta template, que se considera como uno de los pilares de los Web Components y las template string de Javascript, que son una buena alternativa para generar el Shadow DOM con interpolación de datos.

Light DOM a fondo

El Light DOM es un espacio compartido entre nuestro componente web y el DOM general, que podemos utilizar para insertar contenido o configurar nuestro componente. Es una muy interesante característica que debemos conocer.

Shadow DOM a fondo

Para que los componentes web no colisionen unos con otros es muy útil utilizar el Shadow DOM para aislar el DOM y el CSS de cada componente. Esta característica se puede aplicar también a elementos HTML sin necesidad de utilizar Custom Elements, pero es con estos donde cobra todo su potencial. Demos un repaso profundo a las capacidades del Shadow DOM.

HTMLElement a fondo

HTMLElement es una pieza clave, ya que de él heredan todos los componentes web, pero en muchas ocasiones no conocemos bien sus características. Os invitamos a dar un repaso a fondo a sus capacidades y descubrir cómo sacarle todo el partido en nuestros componentes.