jueves, 14 de noviembre de 2013

Prototype en Javascript. ¿Y eso que es?

Hola de nuevo,

Voy a tratar el tema de prototype de forma "literaria", los artículos más técnicos de momento los publico en codeproject.com, ya que tiene más lectores que este estupendo blog.

El tema a tratar hoy es:

Prototype en Javascript. ¿Y eso que es?

Permitirme el defecto de formato, que no de forma, en el título, cosas del SEO :-)

Bien, vayamos al grano, mi profesor del colegio, JA, decía que hay dos normas básicas a la hora de definir algo, una es no incluir la propia palabra en la definición, y la otra es "no decir lo que no es".
Pues bien, para el caso de prototype, encaja bien decir "lo que no es" ya que es una "cosa" que da lugar a mucha confusión según el contexto donde lo leas y quien lo haya escrito, así que mi primer consejo para comprender que es prototype es leer este post, y después no volver a leer ningún otro nunca más, así no nos invadirán las dudas.

Siendo científicos prototype es
"Una propiedad de todos los objetos de Javascript, que actúa como plantilla para los objetos"
 o,
"Una propiedad para añadir propiedades y/o métodos a una clase".

Bien, pues después de estas definiciones wikipedikas, que no ha entendido nadie, yo tampoco, voy a seguir con mi definición de "lo que no es", ya que enciclopedias ya hay muchas, y esto es literatura,

Prototype NO:

1) No son métodos estáticos, "son algo parecido"

2) No son métodos de extensión aunque pueden servir para este propósito

3) Puede servir como herencia, pero no es herencia

Porqué:

1) Es la forma correcta de declarar métodos dentro de objetos (funciones, esto es otro tema) en javascript. Según el ejemplo que veas en Internet, permiten una sintaxis que "hace pensar" que son métodos estáticos, pero en realidad no lo son. Esa sintaxis es la siguiente:
 
           NombreClase.prototype.metodo = function () { codigo }

Bien, ¿Verdad que parece un método estático? Pues bien, no lo es, ya que los métodos declarados de esta forma son llamados por instancias de objetos y el código de estos métodos tiene acceso a las propiedades del mismo. Por tanto no son métodos estáticos aunque su sintaxis lo parezca.

Es la forma correcta de declarar métodos en una clase, pero por un tema de funcionamiento interno de javascript, al añadir los métodos dentro de la propiedad prototype, su definición solo se almacena una sola vez en memoria, cosa muy recomendable si vamos a crear múltiples instancias de una clase, e insignificante si la utilizamos como singleton o "pairLeton". Pero las buenas prácticas, dicen que debes declararlo así.

En Javascript, realmente no existen los métodos estáticos. Eso sí, si un método de prototype no accede a ninguna propiedad de la clase, se parece bastante a un método estático, ¿no?
Pues se podría decir que sí, que "se parece", pero no lo es.

2) No son métodos de extensión, veamos este ejemplo:

Date.prototype.mondayOfWeek = function () {
    return (this.addDays((6 - (7 + (this.getDay() - 2)))));
}

A ver, eso en C# se llama método de extensión.   Cierto, a la clase Date, clase nativa de Javascript de la que no tenemos acceso a su código,  le estamos añadiendo la propiedad "mondayOfWeek", eso sin ninguna duda en .NET se llama método de extensión.

Sí, pero prototype no tiene solo esta finalidad, por tanto prototype "sirve para extender métodos, pero no es exclusivamente eso, por tanto no es un método de extensión. Por hacer una comparativa un "yogur tiene leche" pero "no es leche"

Ojo al dato, prototype también se puede usar para añadir métodos a instancias concretas de objetos, por tanto en ese caso estaría actuando como "decorador"

3) No es herencia pura, sirve para hacer herencia, pero no la herencia que estudiamos de toda la vida, con propiedades publicas/privadas/protegidas, es más bien composición. Con prototype se consigue que una clase "Hijo" contenga a toda una clase "Padre" de la siguiente forma

Hijo.prototype= new Padre();

pero esto no significa que "Hijo" hereda de "Padre" y accede a sus métodos públicos y protegidos, sino que directamente Hijo "Tiene" un Padre entero. Ciertamente se aproxima bastante a la herencia, pero no la de los libros. Todas las instancias de la clase "Hijo" contendrán todas las propiedades y métodos de la Padre, sin distinción de acceso privado/publico.  Se podría decir que es "herencia Full", termino que no debéis buscar porque creo que no existe, pero se entiende, o eso creo, no esto seguro...


Bueno, pues en resumidas cuentas prototype se podría definir como:

"Una propiedad de todos los objetos de Javascript con la que se pueden implementar/simular las características principales de la POO: Herencia, extensión, polimorfismo, decoración, métodos estáticos" 

Si nos podemos a mirar con lupa cada una de estas características siempre encontraremos matices, peros, en los que nos podremos basar para afirmar que "se parece a Herencia, .... " pero "NO lo es"

Y es que los tipets que implementaron prototype para Javascript creo que debían estar pensando en lo siguiente

"La gente critica Javascript porque dicen que no es un lenguaje con funcionalidades POO, pues bien, vamos a hacer una 'cosa', con la que se podrá 'simular' los aspectos principales de la POO"

Y a mi entender, lo consiguieron, efectivamente, y es que estos últimos meses, estoy encantado de conocer mejor Javascript, un lenguaje muy flexible que como mi buen amigo Cancho (principal, y casi único lector de este blog) dice, ha sido injustamente tratado, tal vez por desconocimiento


Bueno, como decía al principio, el blog lo dejo para reflexiones filosóficas, si a alguien le interesan los temas más técnicos puede seguirme en codeproject.com, aquí dejo el link a un articulo, "simular" LINQ para JQuery.
http://www.codeproject.com/Tips/665477/LINQ-to-JQuery

Y en el próximo post hablaré de un cuento muy divertido de los "three monkeys", dejaré un link al cuento, contaré una anécdota y daré mi opinión sobre el.

Si has llegado hasta aquí, tiene mérito, saludos.