El propósito de closures
es simplemente preservar el estado; de ahí el nombre closure
: se cierra sobre el estado. Para facilitar la explicación adicional, usaré Javascript.
Normalmente tienes una función
function sayHello(){
var txt="Hello";
return txt;
}
donde el alcance de las variables está vinculado a esta función. Entonces, después de la ejecución, la variable txt
queda fuera de alcance. No hay forma de acceder o usarlo una vez que la función ha finalizado la ejecución.
Los cierres son construcciones de lenguaje, que permiten, como se dijo anteriormente, preservar el estado de las variables y prolongar así el alcance.
Esto podría ser útil en diferentes casos. Un caso de uso es la construcción de funciones de orden superior .
En matemáticas e informática, una función de orden superior (también forma funcional, funcional o functor) es una función que realiza al menos uno de los siguientes: 1
- toma una o más funciones como entrada
- emite una función
Un ejemplo simple, pero ciertamente no muy útil es:
makeadder=function(a){
return function(b){
return a+b;
}
}
add5=makeadder(5);
console.log(add5(10));
Usted define una función makedadder
, que toma un parámetro como entrada y devuelve una función . Hay una función externafunction(a){}
y una interna. function(b){}{}
Además, define (implícitamente) otra función add5
como resultado de llamar a la función de orden superior makeadder
. makeadder(5)
devuelve una función anónima ( interna ), que a su vez toma 1 parámetro y devuelve la suma del parámetro de la función externa y el parámetro de la función interna .
El truco es que, al devolver la función interna , que realiza la suma real, se conserva el alcance del parámetro de la función externa ( a
). add5
recuerda , que el parámetro a
era 5
.
O para mostrar un ejemplo al menos de alguna manera útil:
makeTag=function(openTag, closeTag){
return function(content){
return openTag +content +closeTag;
}
}
table=makeTag("<table>","</table>")
tr=makeTag("<tr>", "</tr>");
td=makeTag("<td>","</td>");
console.log(table(tr(td("I am a Row"))));
Otro caso de uso común es la llamada expresión de función IIFE = invocada inmediatamente. Es muy común en javascript falsificar variables de miembros privados. Esto se hace a través de una función, que crea un ámbito privado = closure
, porque se invoca inmediatamente después de la definición. La estructura es function(){}()
. Observe los corchetes ()
después de la definición. Esto hace posible usarlo para la creación de objetos con un patrón de módulo revelador . El truco es crear un ámbito y devolver un objeto, que tiene acceso a este ámbito después de la ejecución del IIFE.
El ejemplo de Addi se ve así:
var myRevealingModule = (function () {
var privateVar = "Ben Cherry",
publicVar = "Hey there!";
function privateFunction() {
console.log( "Name:" + privateVar );
}
function publicSetName( strName ) {
privateVar = strName;
}
function publicGetName() {
privateFunction();
}
// Reveal public pointers to
// private functions and properties
return {
setName: publicSetName,
greeting: publicVar,
getName: publicGetName
};
})();
myRevealingModule.setName( "Paul Kinlan" );
El objeto devuelto tiene referencias a funciones (por ejemplo publicSetName
), que a su vez tienen acceso a variables "privadas" privateVar
.
Pero estos son casos de uso más especiales para Javascript.
¿Qué tarea específica estaría realizando un programador que podría ser mejor atendida por un cierre?
Hay varias razones para eso. Una podría ser que es natural para él, ya que sigue un paradigma funcional . O en Javascript: es mera necesidad confiar en los cierres para sortear algunas peculiaridades del lenguaje.