Declaración de clases en Javascript
enero 15, 2009 Publicado en Software y HardwareEtiquetas: javascript
Hace poco desarrollé una librería para manejar las conexiones Ajax de los plugins que había programado hasta el momento, con el fin de eliminar la redundancia de código que se estaba apoderando de la página por cuenta de los scripts que se repetían una y otra vez. Después de hacer esta primera abstracción descubrí un patrón que describía un objeto en los scripts, así que busqué información sobre POO en Javascript para convertir esta librería de funciones en una librería de clases. Por desgracia toda la información que encontraba era confusa y hasta contradictoria, nada de extrañar porque la principal fuente de consulta está compuesta por hilos de charla donde la rigurosidad académica no es una exigencia para que un comentario sea publicado.
Después de varias horas unificando la información, logré comprender los conceptos básicos sobre POO en Javascript. El siguiente código y su documentación describe los aspectos a tener en cuenta.
<script>
//Clase Suma
function Suma(a, b, div) {
var me = this; //Declarando la variable de ámbito.
var c = 0; //Declarando una variable privada.
//Las variables 'a' y 'b' son privadas
// por haber sido llamadas desde el constructor
// de la clase.
me.div = div; //Declarando una variable pública.
//La variable 'div' es privada por haber sido
// llamada desde el constructor de la clase, y
// por lo tanto se ha de declarar la variable
// 'me.div' para ser atendida como variable
// pública.
me.asignar = function(a_x, b_x) { //Función pública
a = a_x; //Artimaña para asignar un valor a una
b = b_x; // variable privada.
}
var sumar = function() { //Función privada
c = a + b;
}
me.visualizar = function() {
sumar(); //Calcula el valor de la variable privada 'c'.
document.getElementById(me.div).innerHTML = c;
//Asigna el valor de la variable privada 'c' al contenido
// 'innerHTML' de la instancia de ámbito global que es
// retornada por la función 'getElementBy' a partir de la
// variable pública de clase 'me.div'.
}
}
</script>
<div id="suma"></div>
<div id="suma2"></div>
<script>
var sum = new Suma(1,2,'suma');
var sum2 = new Suma(3,4,'suma2');
sum.visualizar();
sum2.visualizar();
alert(sum.div);
alert(sum2.div);
</script>
Por extraño que parezca, una clase en Javascript no es más que una función que tiene variables privadas o públicas, y cuyas funciones se declaran como si fueran variables a las que se asigna una función. Para que una variable o función sea privada se deberá declarar con var al inicio, y las variables públicas deberán usar el prefijo de ámbito this (al final del documento explico por qué en el ejemplo uso me en vez de this). Esta norma se aplica tanto a las variables de datos como a las variables que identifican funciones.
Las variables que se ingresan en la declaración de la función que identifica la clase son asignadas como variables privadas, así que en caso de querer asignarlas como variables públicas se tendrá que escribir la línea de código que declare la asignación, porque la máquina virtual solo identifica como variables públicas aquellas que tengan el prefijo de ámbito (this), y por lo tanto usar variable_x será diferente de usar this.variable_x.
Se debe tener mucho cuidado en no emplear nombres de variables privadas al declarar parámetros en las funciones de la clase, porque la máquina virtual por defecto usa los parámetros y no habrá forma de identificar las variables privadas de clase en la función.
Otro aspecto importante a tener en cuenta es que una clase en Javascript es en realidad una función, y por lo tanto ella misma se comporta como su propia función constructora.
Si desean probar este código, recuerden ponerlo dentro del body de una página HTML correctamente estructurada.
El aspecto más desconcertante al inicio del aprendizaje de Clases en Javascript es el que concierne a las variables de ámbito global. La razón por la cual las variables públicas se deben declarar con var es precisamente porque aquellas variables que no sean declaradas con este método serán asignadas como variables globales, es decir, esta variable compartirá el mismo valor en todas las instancias de la clase. Lo mismo pasa con las funciones. Por experiencia propia recomiendo evitar al máximo el uso de variables globales al programar clases, pero esta característica puede ser útil en algunos casos particulares.
Un lector perceptivo se habrá preguntando por qué en el código de ejemplo uso me en vez de emplear el prefijo this para las variables y funciones públicas. La respuesta rápida es que lo hago para facilitar la ampliación de la clase. Por ejemplo, emplear como parámetro para el método setTimeout una función que ha sido declarada como pública no funcionará como se espera si dentro de los parámetros del temporizador se llama con this, pero sí funcionará con me; lo mismo sucederá con las variables públicas declaradas al interior de una función programada para atender un evento. Esto ocurre porque tanto setTimeout como las funciones de respuesta a eventos se ejecutan en procesos externos a la instancia de la clase que los llamó o declaró, y por ende estos nuevos procesos entenderán this como si se tratara de su propio ámbito, por eso declaro al inicio la variable me como variable privada, y la empleo por toda la clase para que los métodos que generan nuevos procesos sepan cuáles instancias emplear al llamar variables y funciones que no son globales.
Buenisimo el aporte. muy claro y didactico.
Al ser tan generico, es aplicable a cualquier caso.
Justo lo que andaba buscando.
Gracias!
Me ha pasado como a ti, he estado buscando algun sitio donde expliquen esto claramente, y es el primero que encuentro.
Acostumbrado a java, veo que javascript tiene una manera bastante extraña de crear una clase. Este articulo se va a marcadores por si acaso.
Un saludo!
Gracias, me a servido mucho esta informacion, tengo unos dias usando javascript y todavia no tenia claro algunas cosas que usaba principalmente en el uso de variables en los objetos.