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

Datos inmutables en Javascript

Datos inmutables en Javascript

En Javascript todo parece mutable, es decir, que se puede cambiar, pero lo cierto es que también nos ofrece varios mecanismos para conseguir que los datos que manejamos, especialmente los objetos, sean inmutables. Te invitamos a descubrir cómo…

Copiar objetos en Javascript

Copiar objetos en Javascript

Copiar objetos no es algo sencillo, incluso se podría decir que en si mismo no es posible, ya que el concepto «copiar» no entra dentro del paradigma de los objetos. No obstante, por medio de instrucciones como Object.assign() hemos aprendido como obtener objetos con las mismas propiedades, pero está técnica no se puede aplicar a todos los tipos de objetos disponibles en Javascript. Vamos a ver cómo podemos copiar cualquier tipo de objeto…

Descubre los Javascript Array Internals

Descubre los Javascript Array Internals

El Array es una de las estructuras más utilizadas en Javascript y no siempre bien comprendida. Hoy os invitamos a analizar el comportamiento interno de este objeto y descubrir cómo Javascript implementa las diferente acciones con los Array y que operaciones internas se realizan en cada caso.

Web Components: pasado, presente y futuro

Web Components: pasado, presente y futuro

Los Web Components aparecieron en el panorama de desarrollo hace ya bastante tiempo. Desde su presentación se les ha prestado mucha atención, pero lo cierto es que no han sido acogidos de forma generalizada, quizás por la difusión de nuevos y potentes frameworks. Nos preguntamos qué ha pasado con este estándar y, sobre todo, que puede pasar de aquí en adelante con el uso práctico de los componentes web.