viernes, 23 de enero de 2009

Extendiendo javascript con prototype y herencia

Hay una forma de extender los objetos de javascript, me explico, digamos que tienes que hacer algo tan simple como es borrar un elemento de un tipo Array, es decir, hacer un array.remove(1), o quieres obtener la posición de un elemento, por ejemplo array.indexOf("string").
Para ello se puede hacer uso de una propiedad llamada prototype, es un objeto que se utiliza como constructor para poder añadir propiedades a los objetos que se crean en este lenguaje.
Por ejemplo para los dos anteriores casos tendríamos algo como:

// remove: elimina un elemento de un array situado en una posición dada,
// o un rango de ellos dando el de inicio y fin
Array.prototype.remove = function(desde, hasta) {
var rest = this.slice((hasta || desde) + 1 || this.length);
this.length = desde <>desde : desde; return this.push.apply(this, resto);
}

// indexOf: devuelve la posición del primer elemento que coincida con el parámetro
Array.prototype.indexOf = function(elemento) {
var retorno = -1;
for(var i=0;i<this.length;i++)
if(this[i] == elemento)
{
retorno = i;
break;
}

return retorno;
}

De modo que cada vez que quieras eliminar algo, en lugar de escribir algo tan sencillo como
var_array.remove(3);
o cuando te interese si un elemento existe y de paso su posición
var_array.indexOf(elemento);
.

El paradigma Prototype permite herencia entre objetos de tipo Prototype Chaining, el cual no permite herencia múltiple, veamos..
Como bien sabréis, en javascript, para definir una clase no hay mas que crear una función:

function objeto()
{
this.atributo1 = "valor";
this.atributo2 = "valor";
this.metodo1 = function(){ ... };
}
var varible = new objeto();


Fácil, ¿no? bueno, al grano, si hiciéramos un objeto que tuviera que heredar de éste, utilizando prototype, la cosa quedaría así:

function objeto2()
{
this.atributo3 = "valor";
this.metodo1 = function() { ... };
}
objeto2.prototype = new objeto();


Quedando así que si te creas un objeto de tipo objeto2 tendrás los atributos de ésta clase, de la de su padre (objeto) y tendrás sobrecargado el metodo1(), por lo tanto utilizarás el del objeto2.
Tal y como he dicho, esto no permite herencia múltiple, para ello existe otro modo de heréncia, el llamado Object Masquerade.
Este tipo de herencia, hace uso del objeto this, cuando se crea el constructor, se le asigna a ese objeto todas las variables y métodos internos de esa clase (a la que llamaremos Base). Pero en javascript, el constructor no es más que una función, por lo cual, puede usarse como método en otra clase que derive de Base (a la que llamaremos Derivada), de modo que las variables y métodos que se creaban en Base, se crean en Derivada. Voy a poner un ejemplo para aclarar:

// Tenemos la clase Base
function Base(valor)
{
this.valor = valor;
this.mostrarValor = function()
{
alert(this.valor);
}
}

// Y ahora la Derivada
function Derivada(valor)
{
this.base = new Base;
this.base(valor); // al hacer esto, el this al que se refiere Base es el this que tiene Derivada
delete this.base;
}


De modo que puedes hacer eso con todas las clases que quieras, luego permite heréncia múltiple.

No hay comentarios:

Publicar un comentario