¿Qué son los Closures?
Mar 05, 2009 | Español | By Crysfel | 11 Comments | Read in EnglishMediante los closures podemos resolver varios problemas cuando desarrollamos componentes o alguna aplicación, es importante conocer este concepto aplicado a JavaScript.
Un closure es la manera en como una función dentro de otra función contenedora puede hacer referencia a las variables después de que la función contenedora ha terminado de ejecutarse. Este concepto puede ser un poco difícil de comprender y de explicar así que veamos un ejemplo.
function sayHi(seconds){
var hi = 'Hi folks!';
setTimeout(function(){
console.info(hi); //Referenciando a la variable ‘hi’
},seconds*1000);
}
sayHi(2);
En el ejemplo anterior se puede ver claramente como la función “sayHi” termina su ejecución y después de 1 segundo se ejecuta la función interna mostrando el mensaje contenido en la variable “hi”, la cual pertenece a la función contenedora, a esto se le llama closure.
Ocultar variables globales
Muchas veces declaramos variables en el “global scope”, es una mala práctica hacer esto por que estas variables pueden interferir con algunas librerías o con el código de algún otro miembro de nuestro equipo. Si utilizamos una función anónima auto ejecutable y hacemos uso de closures podemos resolver de una manera sencilla este problema. A continuación se muestra como hacer esto:
(function(args){
var thisWasGlobal = 'closure!';
window.onload = function(){
console.info(thisWasGlobal);
}
})();
El código anterior encapsula las variables declaradas dentro de la función anónima, de esta manera las variables estarán en un scope donde no hay peligro que sobre escriban a otras variables.
Closures y Scope
Se ha mostrado que un closure permite referenciar variables que existen y pertenecen a la función contenedora. Es importante mencionar que al hacer un closure, éste toma el último valor de la variable de la función contenedora. Un caso muy común es cuando utilizamos un ciclo o loop.
window.onload = function(){
var el = document.getElementById('element');
var events = ['click','mouseover','mouseout'];
for(var i=0;i<events.length;i++){
var item = events[i];
el['on'+item] = function(){
console.info('event: '+item);
}
}
}
Al ejecutar el código anterior se agregan los eventos contenidos en el arreglo “events” al elemento seleccionado, el problema se ocasiona cuando se imprime en la consola el evento que se ejecuta pues siempre imprime lo mismo, en este caso “mouseout”, esto sucede porque la variable “item” contiene a “mouseout” como último valor asignado.
Para solucionar este problema es necesario crear un scope diferente para cada iteración del ciclo, de esta manera se crearán variables diferentes; esto se realiza mediante una función anónima que se auto ejecute. Si tienes alguna duda en cuanto al concepto scope te recomiendo ver el tema anterior. El código quedaría de la siguiente manera.
window.onload = function(){
var el = document.getElementById('element');
var events = ['click','mouseover','mouseout'];
for(var i=0;i<events.length;i++){
(function(){ //función anónima crea un nuevo scope
var item = events[i]; //item pertenece a la function anónima
el['on'+item] = function(){
console.info('event: '+item); //un closure de la función anónima
}
})();
}
}
Si ejecutamos el código anterior veremos que ahora el evento correcto se imprime en la consola.
Conclusiones
En este tema vimos que es un closure y cuán útil es cuando introducimos el concepto de scope, esto es algo que debemos aprender y tener en cuenta a la hora de desarrollar nuestros proyectos.
El tema de closures es complicado, te recomiendo darle una leída a “JavaScript Closures” escrito por Jim Jey, es un excelente material que debes leer.
Como siempre puedes dejar tus dudas o sugerencias en los comentarios, y no olvides de votar en tu red social preferida.







Muchas Gracias por todo este curso.. te felicito, de primerísima calidad