En Javascript no hay clases

En la entrada anterior de este blog os compartí el capítulo This & Object prototypes de la serie You don’t know JS. En esta entrada quiero incidir en que efectivamente, como se deja claro en el libro, en JS no hay clases como en otros  lenguajes. Podemos “simular” su comportamiento pero al final obtendremos un códigfo más complejo y dificil de manetenr por querer usar un patrón de diseño no inherente al lenguaje.

Cuando se habla lenguajes de programación orientados a objetos, se suele omitir si son además, orientados a clases. Para poner un ejemplo, PHP es un lenguaje que permite un uso tanto procedimental como orientado a objetos. De hecho, en su manual oficial solemos encontrar en general ejemplos de ambas aproximaciones para cualquier método que busquemos (por ejemplo cualquier ejemplo de la funcionalidad mysqli). En este lenguaje cuando queremos usar objetos, hemos de instanciar una clase, por ejemplo en el link que os he puesto antes:

Observamos como se instancia la clase mysqli con la palabra reservada new, tras ello podemos acceder a los métodos definidos en la clase a través del operador flecha -> (en el ejemplo $mysqli->query). Si no hemos creado una clase, podemos usar una de las clases predefinidas en PHP que nos permite crear objetos rápidamente, como por ejemplo stdClass :

Pero como hemos visto siempre hemos tenido que insytanciar una clase. Bien, y en Javascript. Pues lo dicho no hay clases. Puedes emularlas pero no cambiará el hecho de que en JS lo que hay son objetos y prototipos. No sólo eso, las clases en lenguajes como PHP son estáticas, es decir, cuando defines un método en una clase si luego creas un objeto instanciándola, vas a obtener una copia de los métodos y propiedades que tenga esa clase en el momento de la instancia. Si creas otro objeto de esa clase, tendrá las mismas copias. Lo mismo sucede si creas una clase hija que herede ede la clase original.

Pero si luego sobreescribes algo en una de las instancias, esto no afectará las otras instancias pues estás recibieron una copia de lo que tenía la clase padre en el momento de la instanciación.

Esto no es así en JS. JS es un lenguaje dinámico basado en prototipos. Esto quiere decir, que no hay copia de objetos. No se copin propiedades ni métodos. En JS lo que sucede es que se relacionan unos objetos con otros a través de sus prototipos. Un objeto puede “heredar” una propiedad de otro objeto y se crea un enlace con el prototipo del primero. Y dado que es un enlace, si el objeto “derivado” modifica la propiedad o método heredado, lo está modificando realmente en el prototipo, por lo que los cambios afectarán a todos los objetos que estén implementando los métodos/propiedades de ese prototipo, incluyendo el objeto original donde se defineron.

Veamos el ejemplo que se muestra en el libro para demostrar esto. Se hace usando la nueva sintaxis de ES6 aunque es lo mismo si no se usa esa sintaxis pues estamos, al final, hablando sde prototipos y no clases:

En el código se crea una clase C con dos métodos uno para inicializar un valor cuando se crea la instancia con new y otro para mostrar el valor por consola. Se crea un primer objeto c1 que ha adquirido el valor 0.4324299. Tras ello se accede al prototypo de C, al método rand y se sobreescribe el método. Se instancia un nuevo objeto c2 con un valor 867 como resultado (de haber multiplicado por 1000). Hasta aquí no hay diferencias con un lenguaje orientado a clases como PHP. c1 recibió unos métodos cuando se instanció y cuancdo se instanció c2, uno de esos métodos había cambiado pudiendo comprobar esto en el resultado obtenido (867).

Lo clarificador viene a continuación cuando se llama de nuevo al método rand() sobre c1, devuelve el valor multiplicado por 1000 porque el método al que referencia, y esa es la palabra clave, referencia no copia, cambió.

Javascript permite que a traves de probiedades como enumerable, writable poder evitar acceder alas propiedades/métodos de un objeto y cambiar su valor. Pero con todo estó, lo que conseguimos es complicar las cosas por obcecarnos en usar una sintaxis “extraña” al lenguaje.

Creo que tal y como se nos propone, hay que “abrazar” el estilo de delegación de comportamiento en nuestro código. Tendremos un código más simple, claro, fácil de entender y mantener y seremos más felices. Un ejemplo también extraído del libro para ilustrar esto. Como realizar el proceso de validación de login con la sintaxis OLOO (Ojetos enlazados con otros objetos):

LoginController es un objeto que se encarga de validar los datos introducidos y AuthController es otro objeto que se encarga de comprobar si existen estos datos en el servidor. Lo que necesita nuestro programa es saber si existe el usuario, comprobar estos datos en el servidor, pero antes de hacer perder el tiempo al usuario (y al servidor), debemos comprobar que los datos han sido correctamente introducidos.

Lo que hacemos es que AuthController delegue la parte de validar los datos introducidos a LoginController mediante Object.create y luego sólo tenemos que llamar al método checkAuth de AuthController. Me código fantástico y práctico para ejemplificar lo que estamos contando.


Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *