JavaScript Closures
Las Closures son funciones que se refieren a variables independientes.
Un ejemplo vale más que mil palabras:
function myFunc() {
var message = 'Hello';
function getMessage() {
console.log(message);
}
getMessage();
}
La función myFunc
crea una variable local message
y una función anidada getMessage
. La función anidada getMessage
es una Closure y aunque no tiene variables locales es capaz de acceder a las variables de la función padre.
Vamos a hacerlo más interesante:
function myFunc() {
var message = 'Hello';
function getMessage() {
console.log(message);
}
return getMessage;
}
var fn = myFunc();
fn(); // Hello
Este código tiene exactamente el mismo efecto que el anterior. La principal ventaja es que estamos exponiendo públicamente la función getMessage
, la única en tener acceso a la variable local message
de la función myFunc
. Esto hace que la variable message
no se pueda modificar y cada vez que se quiera acceder a ella se tenga que invocar la función devuelta por myFunc
, en este caso la que dejamos en la variable fn
.
Funciones y variables privadas
A diferencia de otros lenguajes, JavaScript no ofrece la posibilidad de declarar métodos privados.
Sin embargo gracias a las Closures podemos emular funciones privadas además de poder encapsular el código.
Veamos un ejemplo:
var counter = (function() {
var value = 0;
function modify(val) {
value += val;
}
return {
increment: function() {
modify(1);
},
decrement: function() {
modify(-1);
},
getValue: function() {
return value;
}
}
})();
counter.getValue(); // 0
counter.increment();
counter.getValue(); // 1
counter.decrement();
counter.getValue(); // 0
En este ejemplo tenemos una función counter
. Esta función tiene una variable local value
privada y método modify
privado. Así mismo se están devolviendo 3 métodos increment
, decrement
y getValue
que son públicos.
De esta manera para incrementar el valor del counter
tenemos que llamar al método público increment
, para disminuir el valor hay que invocar el método decrement
y para obtener el valor en curso del counter
el método getValue
.
Usar Closures de este modo también se conoce como Module Pattern.