Prototipos en javascript

Hemos llegado a uno de los conceptos más extraños, los prototipos en javascript. De hecho muchos autores y desarrolladores de alto nivel tienen problemas para definir y utilizar este concepto, de modo que yo voy a intentar explicarlos de forma que nos sirva a todos para tener un concepto de los mismos.

Para empezar comenzaremos diciendo que todos los objetos dependen de un prototipo y que los prototipos son objetos, es más cualquier objeto puede ser un prototipo… bueno esto dicho así la verdad es que suena muy lioso pero recapitulemos un poco y dejemos de hablar como algunos políticos…

Lo que queremos decir es que un prototipo es un objeto del que otros objetos heredan propiedades, y los objetos siempre heredan propiedades de algún objeto anterior, de este modo solo el objeto original y primigenio de javascript es el único que no hereda de nadie…

Bien, de este modo podemos ver que:

  • objetos creados por ejemplo de forma literal o new Objetc(), heredan directamente del objeto Object.prototype.
  • objetos creados con new Date(), heredan de Date.prototype.
  • Y así sucesivamente

Es el objeto Object.prototype el primer eslabón de la cadena, el padre u objeto primigenio como a mi me gusta llamarlo (soy un fan de Lovecraft, no puedo evitarlo) de este modo todos los objetos de JS heredan de él, ya sean arrays, fechas, funciones…

Creando un prototipo

Ahora que ya tenemos más o menos claro que es un prototipo podemos empezar a manejarlos y para ello lo primero que tenemos que hacer es crearlo. Lo vamos a hacer creando una función constructora de objeto como la siguiente:

function persona(nombre, apellido, edad, ojos) {
    this.nombre = nombre;
    this.apellido = apellido;
    this.edad = edad;
    this.ojos = ojos;
}

De esta forma podemos crear objetos por medio de la palabra reservada new para crear nuestros objetos

var forajida = new persona('Juana', 'Calamidad', 34, 'castaños');
var sheriff = new persona('Wyatt', 'Earp', 40, 'verdes');

Una vez que ya tenemos los objetos podemos empezar a trabajar con ellos de las siguientes formas:

Agregando una propiedad a un objeto

Para agregar una propiedad a un objeto es muy sencillo tan solo tenemos que añadirla de la siguiente forma:

forajida.nacionalidad = "Estado Unidense";

De este modo la propiedad solo existe para el objeto al que se le introduce, en nuestro caso sheriff no tendría nacionalidad.

Agregando un método a un objeto

A la hora de agregar un método a un objeto también es muy sencillo tan solo hay que hacerlo así:

sheriff.nombreCompleto = function () {
    return this.nombre + " " + this.apellido;
};

De este modo el método sólo pertenecerá a sheriff y no a forajida.

Agregando propiedades a un prototipo

A la hora de trabajar con los prototipos no podemos agregarlos de la misma forma que a los objetos, ya que el prototipo no es un objeto existente, es por ello que debemos de hacerlo agregando la propiedad a la función constructora, y hay que tener en cuenta que la propiedades del prototipo pueden tener valores por defecto.

function persona(nombre, apellido, edad, ojos) {
    this.nombre = nombre;
    this.apellido = apellido;
    this.edad = edad;
    this.ojos = ojos;
    this.nacionalidad = "Estado Unidense";
}

Agregando métodos a un prototipo

En la función constructora, también se pueden introducir métodos que puedan utilizarlos todos los objetos, tal y como vemos a continuación:

function persona(nombre, apellido, edad, ojos) {
    this.nombre = nombre;
    this.apellido = apellido;
    this.edad = edad;
    this.ojos = ojos;
    this.nombreCompleto = function() {return this.nombre + " " + this.apellido;};
}

Modificando el prototipo en ejecución

Todo esto está muy bien, podemos ampliar nuestros prototipos como queramos a la hora de generar código pero todos sabemos que puede ser interesante modificarlos en ejecución dependiendo de las acciones del usuario.

La verdad es que es algo muy sencillo, como vemos en este ejemplo donde introducimos la propiedad a la función constructora:

function persona(nombre, apellido, edad, ojos) {
    this.nombre = nombre;
    this.apellido = apellido;
    this.edad = edad;
    this.ojos = ojos;
}
persona.prototype.nacionalidad = "Estado Unidense";

Como vemos solo hace falta añadir prototype y la nueva propiedad a función para añadirla.

De forma muy similar podemos añadir métodos a un prototipo utilizando la propiedad prototype como vemos a continuación:

function persona(nombre, apellido, edad, ojos) {
    this.nombre = nombre;
    this.apellido = apellido;
    this.edad = edad;
    this.ojos = ojos;
}
persona.prototype.nombreCompleto = function() {
    return this.nombre + " " + this.apellido;
};

Así podemos añadir las funciones que necesitemos.

Como norma general hay que tener en cuenta que NUNCA se deben de modificar los prototipos estándar de JavaScript