Closures
Un closure es una función que devuelve otra función, teniendo la segunda acceso a los datos de la primera, es decir comparten contexto.
Veamos un ejemplo sencillo
function heroName(surname){
return function(name){
console.log(name + ' ' + surname);
}
}
var dr_Manhattan = heroName('Osterman');
console.log(dr_Manhattan('Jon'));
Como veis el concepto es bastante sencillo, lo primero instanciamos heroName con su parámetro surname como Osterman, eso lo que hace es asignar la función que retorna a la variable dr_Manhattan, por lo que ahora mismo dr_Manhattan se ha convertido en un método que espera recibir un nombre por parámetro y que en su contexto tiene acceso al parámetro surname.
Tambien podemos devolver varias funciones no solo una, vamos a cambiar un poco nuestra función de retorno:
function heroName(surname){
return {
getHeroData: function(name){
console.log(name + ' ' + surname);
},
setHeroNewName: function(newName){
name = newName;
},
setHewNewSurname: function(newSurname){
surname = newSurname;
}
}
}
Ahora ya no podemos usarla igual que antes, estamos devolviendo objetos, por lo que tenemos que llamarlos. Lo primero vamos a usar la que seria homónima a la de antes, se decir después de la nueva función ponemos
var dr_Manhattan = heroName('Osterman');
dr_Manhattan.setHeroNewName('Jon');
dr_Manhattan.getHeroData();
Esta nos devuelve lo mismo de antes. Como vemos ahora la variable dr_Manhattan funciona como una clase con varios métodos(en este caso lo hemos planteado como métodos GETTER y SETTER). Ahora vamos a ver que pasa si usamos el resto, añadimos a continuación:
dr_Manhattan.setHeroNewName('Doctor');
dr_Manhattan.setHewNewSurname('Manhattan');
dr_Manhattan.getHeroData();
Con obtendríamos estos resultados:
Como vemos hemos creado una especie de constructor Héroes de una manera relativamente sencilla.
Prototypes
Bien lo siguiente que veremos serán los prototypes. ¿Que es un prototype? Un prototype es una propiedad que tienen todos los objetos de JavaScript(y como casi todo es considerado un objeto son muchas cosas jejejej) y que comparten los que son del mismo del mismo tipo aunque ya hayan sido creados. Dentro de un prototype podemos tener casi de todo. Veamos un ejemplo:
//Tenemos un constructor en este caso de clones
//del Dr.Manhattan
function dr_Manhattan_Clone(cloneNumber){
this.cloneName = 'clon' + cloneNumber;
}
Para que veamos que este constructor (que es un objeto) ya tiene la propiedad prototype hagamos un console.log para ver que tiene
console.log(dr_Manhattan_Clone.prototype)
Esto nos mostrará
No tiene nada pero hemos comprobado que por lo menos no da error, es decir, que es una propiedad válida de nuestro objeto
Ahora creemos un par de clones y mostremos su nombre o número de clon
var cloneOne = new dr_Manhattan_Clone(1);
var cloneTwo = new dr_Manhattan_Clone(2);
console.log(cloneOne.cloneName);
console.log(cloneTwo.cloneName);
Todo normal
Por cierto antes de seguir en este caso iremos acumulando código e iremos viendo todo el log desde el principio.
Bueno en la última imagen hemos visto que teniamos el nombre de nuestros clones como era de esperar. Veamos ahora que tienen nuestros clones
console.log(cloneOne);
console.log(cloneTwo);
Bien como vemos son objetos de tipo dr_Manhattan_Clone que tienen una propiedad cloneName con su nombre o número.
Todo normal hasta aquí no?
Ahora creemos nuestro primer prototipo, decimos que clon tiene conocimiento sobre la materia y cual no(haremos uno un poco menos listo :P )
dr_Manhattan_Clone.prototype.matterCrontol = function(matter){
this.matterKnowledge = matter;
}
He creado un prototipo llamado matterCrontol que básicamente espera que le digamos si el clon tiene conocimiento de la materia o no. Vamos a ver que tiene ahora la propiedad prototype de nuestro constructor
console.log(dr_Manhattan_Clone.prototype)
Vaya si nos fijamos en la primera y la última línea vemos como ahora sí tenemos algo dentro de la propiedad prototype de nuestro constructor.
Bien pues si la teoría es correcta nuestros clones ya creados deberían poder usar esta propiedad, pues comprobemoslo
cloneOne.matterCrontol(true);
cloneTwo.matterCrontol(false);
console.log(cloneOne);
console.log(cloneTwo);
Si ejecutamos vemos como no se queja, si no que ademas ahora nuestros clones tienen otra propiedad más que ha sido asignada al ejecutar el método matterControl en cada clon.
Como tal podríamos seguir asignando prototypes a nuestro constructor y lo tendríamos disponible en todas nuestras instancias de clones. Todo esto se parece un poco a la herencia de otros lenguajes no??
Bueno puede que a lo mejor no le veáis muchísima utilidad, pero y si os digo que podemos asignar prototypes a objetos propios de JavaScript como al objeto Array por ejemplo??
Miremos primero el objeto Array, si nos fijamos en la parte izquierda podemos ver que realmente todos los métodos que usamos en los objetos ¡¡son prototypes!!, por lo que solo tendríamos que añadir otro prototype al objeto array para que lo tengan todos.
Array.prototype.sum = function(){
return this.map(function(x){
return x + 5;
})
}
Bien he creado un protoype sum, que recorre todos los números de un array y le suma 5.
Si la teoría es cierta, ahora cualquier array que creemos podrá usar esa propiedad
var numbers = [1,2,3,4,5];
var result = numbers.sum();
console.log(result);
Y si ejecutamos vemos como si que funciona
Probemos con otro array
var numbers = [1,2,3,4,5];
var result = numbers.sum();
console.log(result);
var numbers2 = [5,10,15,20,25];
console.log(numbers2.sum());
Y el resultado es
Pues como veis ahora podemos usar ese método en todos nuestros arrays, por lo que realmente puede llegar a ser muy útil para ciertos entornos donde necesitamos que muchos objetos de repente tengan que hacer algo que antes no hacian, incluso nos puede servir para generalizar métodos y que varios objetos puedan usar el mismo método (pero esto lo dejaremos para otra ocasión)
Ya va quedando poco para empezar a trabajar con Node no os preocupéis.
Nos vemooossssssss.







