jQuery Blues: 9. Objetos y prototipos

Para comprender mejor cómo funcionan las funciones en jQuery, antes conviene saber qué son los objetos prototipados de JavaScript.

klimt

archivado en: JavaScript / 20 marzo, 2013 / taller:

Retomo esta serie que tenía un poco descuidada. Lo siento mucho para los que me habéis escrito diciendo que siguiera con ella cuanto antes, pero es que entre el curro, mi vida personal, las otras series en curso y mi extraordinaria habilidad para apasionarme con cualquier tema que se me cruza en el camino esto es un desastre, jajajaaa... Bueno, al lío ^^.

En esta entrada y la siguiente vamos a ver cómo son las funciones en jQuery. Trataremos cuestiones mucho más complicadas que las anteriores, pero a cambio, conseguiremos entender mejor algunos conceptos clave de la «programación prototipada» y JavaScript.

Funciones en JavaScript

Ya sabemos qué es una variable, un valor almacenado que se puede modificar dinámicamente, y qué es una función, un conjunto de instrucciones que a veces devuelven un resultado. Recordemos cómo funcionan en JavaScript.

En su forma más simple, se incluyen entre los tags <script></script> (en HTML5) en el head:

<script>

function soyUnaFuncion () {

alert ('Estoy funcionando');

}

</script>

Y luego se llaman, se invocan, en cualquier parte del código mediante un evento o al cargar la página (onload...).

<a href="#" onclick="soyUnaFuncion()">Enlace a la función</a>

A la función podemos pasarle parámetros, es decir, datos, indicándolos en el paréntesis de la declaración. Con esos datos, las funciones pueden hacer cosas, como en el ejemplo, que se muestra una cadena de texto en el alert.

<script>

function soyUnaFuncion (recogeParametro) {

var parametroRecogido = recogeParametro;

alert (parametroRecogido);

}
</script>

...

<a href="#" onclick="soyUnaFuncion('parámetro')">Enlace a la función</a>

Además, se pueden preparar funciones «autoejecutables», es decir, que se ponen en funcionamiento nada más cargar la página. Su sintaxis, al menos una de las posibles, en la que no me voy a detener ahora, es esta.

<script>

(function(window, undefined) {

alert ("Me he autoejecutado");

})(window);

</script>

Objetos y prototipos

Esta manera de incluir código JavaScript en un sitio web es muy rápida y permite hacer un apaño cuando vamos volados en una página de bajo presupuesto para validar un formulario o menudencias semejantes. Pero genera, al menos, dos problemas. El primero es que el código está todo desordenado: las funciones revolotean por el header al alcance de cualquiera. ¿Qué ocurre, por ejemplo, si pasado un tiempo alguien retoma esa página y por error llama a una función de la misma manera que la anterior? Pues que ya la habríamos liado : ).

Y el segundo problema es que obliga a rescribir código que sirve para lo mismo. Por ejemplo, si tenemos dos formularios, habría que escribir sendas funciones para controlarlos: un desperdicio de tiempo y esfuerzo durante el desarrollo y el mantenimiento. En fin, que no mola.

JavaScript es un lenguaje «orientado a objetos basado en prototipos», un galimatías que entenderemos bien a continuación. Un prototipo es una especie de molde, de plano, con el cual se pueden sacar tantas copias, objetos, como se necesiten. Por ejemplo, un prototipo podría ser la fórmula de la cerveza —cebada fermentada con lúpulo—, con la que podemos sacar distintos objetos —Maho, Coronita, Cristal, Guiness—, cada uno con sus propias peculiaridades.

El «prototipo» es lo que se conoce en los lenguajes de programación orientada a objetos (poo) como una clase y los objetos como instancias.

Una gran ventaja del trabajo con clases o prototipos es que podemos realizar variantes del plano original de forma muy sencilla mediante un proceso que se conoce como «herencia», que consiste en reescribir algunas partes del modelo original para adaptarlas a nuevas necesidades, sin alterar para nada el modelo madre, del que se pueden seguir sacando nuevas variantes, además de usarlo tal cual está.

Pero no nos adelantemos, que esto lo entenderemos mejor al final de la entrada, y de momento quedémonos solo con que, trabajando con prototipos y objetos en JavaScript, podemos optimizar el esfuerzo de desarrollo y mantenimiento y, además, conseguir un código mucho más sólido y limpio.

Bueno, vamos a ver un ejemplo, que es como se entienden estos líos.

Un troll modélico

Para entender qué es un objeto prototipado podemos crear un modelo universal de troll, esas simpáticas criaturas llenas de mocos de la mitología escandinava, lo cual es tan sencillo como escribir una función anónima como valor de una variable (que es una variable-objeto):

<script>

var Troll = function () {

// aquí irán los métodos y propiedades del objeto Troll

}

</script>

Et voilá, ya tenemos un modelo de Troll; pero es una abstracción de bicho, es la trollidad, todo aquello que puede ser un troll. Si queremos introducir un troll en concreto en nuestro código hay que crear un objeto a partir de esta entidad abstracta, para lo cual hay que asignarla al nombre que vaya a tener nuestro objeto concreto mediante la palabra new.

var miTroll = new Troll ();

Entonces, ahora tenemos la trollidad, definida en el modelo Troll, y además un objeto troll en concreto denominado miTroll. Si necesitáramos otro bicho mocoso bastaría con crearlo de la misma manera.

var miOtroTrollnew Troll ();

Propiedades

Los objetos pueden contener variables, que en este contexto se denominan «propiedades», que luego serán comunes a todos los objetos instanciados del modelo original, aunque cada una con su propio valor. Por ejemplo, así definiríamos tres propiedades para nuestro modelo Troll: el nombre, pues todos estos bichos tienen un nombre, lo que pesa, pues todos son grandotes y la cantidad de mocos que generan por hora.

var Troll = function () {

var nombre;

var peso;

var mocos;

}

Ahora, todos los objetos trolls creados a partir de este modelo tendrán un nombre, un peso y mocos. Pero, para que funcione de verdad hay que hacer un pequeño cambio en el código anterior y es referirse a las propiedades (a las variables) con el prefijo this, que indica que pertenecen a este modelo en concreto.

var Troll = function () {

this.nombre;

this.peso;

this.mocos;

}

De esta manera, estamos indicando que son las propiedades de este modelo. (Este tema es más complejo, pero vamos a dejarlo así xD).

Constructores

En la poo se denominan funciones constructoras a las que sirven para inicializar una clase, es decir, las que recogen los parámetros iniciales que definen cada objeto en concreto. En nuestro caso, esta función constructora es la función anónima que se pone al inicio. Por lo tanto, como tenemos tres propiedades, en esta función constructora pondremos tres variables que pasaremos a las respectivas propiedades.

var Troll = function (recogeNombre, recogePeso, recogeMocos) {

this.nombre = recogeNombre;

this.peso = recogePeso;

this.mocos = recogeMocos;

}

Ahora cuando declaremos un nuevo objeto troll ya podemos pasarle parámetros a la trollidad que hagan de nuestro bicho algo único ^^.

var miTroll = new Troll("Zasprist", 120, 4);

Para acceder a las propiedades del nuevo objeto, en JavaScript, se utiliza la llamada notación de puntos. Así, si ahora queremos saber qué engendro hemos creado, podríamos hacer algo así:

var miTroll = new Troll("Zasprist", 120, 4);

var cadena = "El nuevo troll se llama "+miTroll.nombre;

var cadena = cadena+" y pesa "+miTroll.peso+" kilos";

alert (cadena);

O, si nos molesta el alert, en su lugar podemos poner esto y verlo por la consola del Chrome o el Firefox (F12).

console.log(cadena);

En los dos casos nos dirá que «El nuevo troll se llama Zasprist y pesa 120 kilos».

Métodos

Hay varias maneras de añadir métodos, es decir, funciones, a un «modelo», pero vamos a ver solo la que nos permite tener todo el código que le atañe en el mismo sitio y es muy similar a la manera en que declarábamos las propiedades:

...

this.tragar = function metodoTragar () {

console.log("Soy "+this.nombre+" y acabo de comerme algo");

}

...

Ahora la trollidad tiene una acción, un método, que es tragar, a la cual podemos acceder casi igual que antes, pero añadiendo los dos paréntesis al final característicos de las funciones.

// Esto muestra por consola: Soy Zasprist y acabo de comerme algo

miTroll.tragar();

Por supuesto, podemos enviar parámetros al método...

this.tragar = function metodoTragar (recogeComida) {

this.comida = recogeComida;

console.log("Soy "+this.nombre+" y acabo de comerme un "+this.comida);

}

...

// Esto muestra por consola: Soy Zasprist y acabo de comerme un jabalí

miTroll.tragar("jabalí");

Herencia

Como decía, otro concepto clave de la programación orientada a objetos es el concepto de «herencia», esto es, la capacidad de que una clase herede los métodos y propiedades de su ancestro. Esto es muy útil, ya que nos permite reutilizar el código y otras ventajas que no vienen al caso, creando nuevas clases que incorporan nuevas funcionalidades que no tiene la clase madre.

En JavaScript, la herencia se consigue mediante la propiedad .prototype, que no vamos a ver en profundidad porque es un quilombo de cuidado :P. Lo único que nos interesa saber ahora es que podemos «heredar» los métodos y propiedades de un objeto de esta forma tan sencilla que vamos a ver a continuación.

Ya tenemos nuestro plano maestro para hacer trolls, lo que en poo sería una clase. Ahora vamos a preparar los planos para otro tipo de bicho, los trolls azules, que tienen una propiedad -el color- y un método, la capacidad de comer mocos.

var TrollAzules = function (recogeColor) {

this.color = recogeColor;

this.comerMocos = function metodoMocos () {
}

}

Y para crear un objeto a partir del molde de la TrolliAzulidad sería tan sencillo como antes...

var miTrollAzul = new TrollAzules("azul");

Ahora bien, un troll sin nombre ni peso ni mocos es un asco de troll, así que podemos hacer que el objeto TrollAzules herede los métodos y propiedades del objeto Troll mediante la propiedad .prototype (observad cómo se inicializa el constructor de la clase padre al «prototiparla».

TrollAzules.prototype = new Troll("Turumbulillos", 120, 14);

var miTrollAzul = new TrollAzules("azul");

Ahora imaginemos que el método comerMocos tuviera estas instrucciones:

this.comerMocos = function metodoMocos () {

console.log ("Soy "+this.nombre+". Un troll "+this.color+" que come "+this.mocos+" mocos a la hora");

}

Aunque el objeto TrollAzules no tiene las propiedades de nombre y mocos, seguiría funcionando, pues las ha heredado del objeto Troll y mostraría por la consola algo así: «Soy Turumbulillos. Un troll azul que come 4 mocos a la hora».

Epílogo: objetos globales

Decía al principio que todo en JavaScript es un objeto. Sin profundizar en esta afirmación, seguro que más de uno la entenderá a la que haya escrito 4 líneas en este lenguaje, pues no habrá sido raro que haya tenido que poner cosas como estas:

miArray = new Array();

miFecha = new Date();

"Cadena de texto".indexOf ("ocurrencia");

¿Qué estamos haciendo ahí? Pues en los dos primeros casos instanciar dos objetos del objeto-modelo Array y Date respectivamente y, en el tercero, emplear el método indexOf del objeto-modelo String, que son, los tres, objetos globales de JavaScript.

Bueno, pues ahora que ya sabemos qué es un objeto prototipado, podemos ver cómo funcionan las funciones en jQuery, pero eso será en la siguiente entrada, que esta ya ha quedado kilométrica, para variar 0_o.

|| Tags: , , ,

valoración de los lectores sobre jQuery Blues: 9. Objetos y prototipos

  • estrellica valoración positiva
  • estrellica valoración positiva
  • estrellica valoración positiva
  • estrellica valoración positiva
  • estrellica valoración positiva
  • 4.6 sobre 5 (23 votos)

¿Te ha parecido útil o interesante esta entrada?
dormido, valoración 1 nadapensativo, valoración 2 un poco sonrisa, valoración 3 a medias guiño, valoración 4 bastante aplauso, valoración 5 mucho

Tú opinión es muy importante, gracias por compartirla!

2 respuestas a “jQuery Blues: 9. Objetos y prototipos

  1. muy bueno el artículo, yo he querido hacerlo y me ha saltado una duda, quise hacer lo siguiente, cargar dos js, en uno una clase con las cosas básicas y en el otro js instanciarla y usarla y no lo hace, no vé la clase. Es que no funciona así? cómo podría hacerlo?