jueves, 29 de marzo de 2012

Classes in javascript

Hola a todos!! Llevaba ya mucho tiempo sin escribir!

El caso es que estoy enfrascado en la implementación de un framework en JavaScript para la creación de juegos en HTML5.
Algo esencial para conseguir que el framework sea lo suficientemente general, reutilizable y flexible, es que esté basado en clases!

Para no extenderme! Las clases en javascript son un recurso impresionante!! son fáciles de implementar, ahorran tiempo, y obtenemos un código limpio, fácil de leer y modificar.

En los lenguajes para la parte del servidor web como Java y PHP la palabra clave para definir una clase es "class"! En JavaScript la palabra clave es la ya conocida function!

Así es! las clases en JavaScript son funciones!

Imaginemos que vamos a hacer un programa web en JS, (si digo JS digo JavaScript que nadie se vuelva loco!), el programa tendrá muchos robots, podrán ser de muchos colores y cada robot tendrá unas coordenadas de posición 'x' e 'y'.
La clase sería como sigue:

function Robot(){
this.x = 0;
this.y = 0;
this.color = "#112233";
}

La palabra this, nos permite definir las propiedades y métodos propios de la clase.

Ya tenemos la clase creada!, ¿cómo creamos un objeto de tipo robot?

var robot1 = new Robot();
De esta forma hemos conseguido definir una variable llamada "robot1" de tipo Robot!!
Lo que ha pasado es lo siguiente, se ha ejecutado la función Robot() (llamada función constructora de la clase), al emplearse la palabra clave "new" el intérprete de JS ha guardado en memoria una instancia concreta de Robot, que contiene 3 espacios de memoria donde están definidos los valores de "x", "y", "color", que son las propiedades definidas como propias de la clase, gracias al uso de la palabra clave "this".

Acceder a la lectura de las propiedades del objeto es tan fácil como esto:


var coordenadax = robot1.x;
var coordenaday = robot1.y;
var color = robot1.color;



Y modificar sus propiedades es tan simple como esto:


robot1.x = 10;
robot1.y = 2;
robot1.color = "#112233";

La clase que hemos definido tan sólo contiene propiedades, pero algo vital en las clases son las funciones!!
Supongamos que tenemos 3 robots en el programa y necesitamos pintar las coordenadas de cada robot siguiendo un formato en concreto:
"x:valor,y:valor"
Podríamos hacer lo siguiente:

document.write("x:"+robot1.x+",y:"+robot1.y);
document.write("x:"+robot2.x+",y:"+robot2.y);
document.write("x:"+robot3.x+",y:"+robot3.y);

Este caso es simple, pero y si la función de pintado requiriera ejecutar un proceso más complejo, con condicionales, bucles, etc? Deberíamos repetir todas esas líneas de código por cada robot!!

Esto en cambio es más fácil!!


function Robot(){
this.x = 0;
this.y = 0;
this.color = "#112233";
this.paintCoords = function(){
document.write("x:"+this.x+",y:"+this.y);
}

}

De la misma forma que definíamos las propiedades de la clase, usando la sintaxis "this.nombre_funcion = function(){...}" definimos los métodos propios de la clase.

Ahora podemos llamar al método paintCoords de cada objeto!

robot1.paintCoords();
robot2.paintCoords();
robot3.paintCoords();

Hay algo IMPORTANTE que he comentado antes! Cuando definimos algo dentro de la función mediante la palabra "this", el intérprete crea en memoria un espacio determinado para esa variable propia de la clase, ya sea una propiedad o método!! Es decir, que por cada variable que creemos de tipo Robot, estaremos copiando el código de las funciones que estén definidas mediante "this"!! QUÉ DESPILFARRO DE MEMORIA!!

Por suerte, JavaScript tiene un recurso: prototype
Como indica la palabra, prototype nos permite definir el prototipo de la clase, es decir, definir la propiedad o función que estará disponible para todas y cada una de las instancias de la clase. Así pues solamente existirá una copia de dicha propiedad o función en memoria, independientemente del número de instancias o variables de clase que creemos.

Vamos a redefinir el método "paintCoords"! Ahora lo incluiremos en el prototipo de la clase!

function Robot(){
this.x = 0;
this.y = 0;
this.color = "#112233";
}
Robot.prototype.paintCoords = function(){
document.write("x:"+this.x+",y:"+this.y);
}

Como podéis ver, la sintaxis es:
NombreClase.prototype.nombreFuncion = function(){...}
Para incluir una propiedad compartida por todas las intancias sería:
NombreClase.prototype.nombrePropiedad = valor;

Una vez definidos tanto métodos como propiedades propios de la clase, su método de empleo es el mismo que para los que están definidos mediante this:

robot1.paintCoords();

Con todo esto, ya podéis crear de forma eficiente vuestras clases propias y usarlas además de una forma eficiente sin consumir en exceso la memoria de los navegadores!

Con esto termina el tutorial sobre la creación de Classes in JavaScript. Espero que os sea de gran ayuda!
Un saludo a todos!!