Trabajando con closures en JavaScript

Las closures las vemos todos los días cuando trabajamos con JavaScript. Las podemos encontrar en todas las librerías y las deberíamos usar en todos nuestros códigos. Esta frase que parece obvia no siempre es así, otras veces si se usan pero no se acaban de entender, aunque en internet hay bastante información sobre el tema he visto interesante escribir un poco sobre ello.

¿Que es una closure?

Es una función que evaluamos en un entorno determinado y que contiene una o más variables de uno o varios entornos, simplificando la definición hablamos de una función que depende de una información no contenida en ella (es decir externa, de otro entorno)  y esta función pasa a llamarse closure una vez es evaluada (llamada).

Ejemplo básico

function entorno() {
	var i = 1; // declaramos una variable

	// declaramos una función que hace algo y retorna un resultado

	var incrementa = function () { 
		i = i * 2;
		return i;
	}

	// retornamos la función anterior

	return incrementa;

}

var test = entorno();
/* Ahora en test tengo guardada una función compuesta por una variable i, una variable incrementa y que retorna esta última variable

*/

console.log(test()); // Veremos un 2 en la consola

console.log(test()); // Veremos un 4 en la consola

Básicamente lo que acaba de ocurrir es que en test hemos guardado entorno de manera que entorno es declarado por primera vez y guarda una variable i que vamos actualizando en cada llamada al llamara a incrementa().

Cada llamada a esta función es una closure

function colorea(r,g,b) {
    var rgb = 'rgb(' + r +',' + g +',' + b +')';
	return function() {
		console.log('%c Mensaje de prueba ', 'color: ' + rgb);
	};

}

var prueba = colorea(255, 100, 30);
var prueba2 = colorea(100, 100, 255);
prueba();
prueba2();

Lo que vemos en el ejemplo anterior son dos closure que nos van a dar dos resultados distintos aunque están basado en una función.

Los parámetros en una closure

Otra cosa interesante a remarcar es que como hemos podido ver la primera vez que llamo a la closure se ejecuta la función de manera que si le paso un parámetro ya me lo he ‘guardado’ se ve mejor con este ejemplo

function test(param) {
    var saluda = 'Hola ';
	return function() {
		console.log(saluda + param);
	};

}

var palabra = 'Quique';
var prueba = test(palabra); 

prueba(); // enseña Hola Quique

palabra = 'Carlos';

prueba(); // enseña Hola Quique

Podemos comprobar en este ejemplo que aunque hemos modificado la variable palabra la función test ya había sido ejecutada de manera que en prueba yo tenía algo del estilo:
var prueba = function() { console.log( ‘Hola Quique’) };

De manera que para mi código por mucho que ejecute prueba luego ya le da igual lo que haga con palabra

Caso práctico

En el siguiente ejemplo podemos ver una función anónima en la que tendremos dentro definida otra función, estamos en un caso de closure, podemos ver su comportamiento de una manera bastante clara si ejecutamos este código.


// Defino un objeto

window.MyApp = {
	test: 1,
	Lorem: {
		Ipsum: {
			sum: function(a, b) {
				return a + b;
			}
		}
	}
};

(function($, global, App, sum){
    var num = 1; // nunca podré modificar este valor directamente

	App.newSum = function(){
		alert(num + App.test) // 1 + x = y

	}

	alert(sum (5, 10)); // 15 (primero en aparecer)

	App.setNum = function(newnum) { // de esta manera modifico la variable num

		num = newnum;
	}
})(jQuery, window, window.MyApp, window.MyApp.Lorem.Ipsum.sum);

MyApp.newSum(); // 1 + 1 = 2; (segundo)

MyApp.test = 2;
MyApp.newSum(); // 1 + 2 = 3; (tercero)

MyApp.setNum(20);
MyApp.newSum(); // 20 + 2 = 22; (cuarto)

 

I use JavaScript, TypeScript, .NET, Node, Cordova and SASS for Web and App development, working at Plain Concepts and HelpDev founder.

Related Posts