El propósito de closures
es simplemente preservar estado; por lo tanto, el nombre closure
- se cierra sobre el estado.
Para facilitar la explicación, 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 del alcance. No hay forma de acceder o usarla después de que la función haya finalizado su ejecución.
Los cierres son construcciones de lenguaje, que permiten, como se dijo anteriormente, preservar el estado de las variables y prolongar 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 y ciencias de la computación, 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
- genera una función
Un ejemplo simple, pero 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 externa function(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% código%. makeadder
devuelve una función anónima ( inner ), que a su vez toma 1 parámetro y devuelve la suma del parámetro de la función outer y el parámetro de la Función interna .
El truco es que, mientras se devuelve la función inner , que realiza la adición real, se conserva el alcance del parámetro de la función externa ( makeadder(5)
) . a
recuerda , que el parámetro add5
era a
.
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 el denominado IIFE = expresión de función inmediatamente invocada.
Es muy común en javascript para falsificar variables de miembros privados. Esto se realiza a través de una función, que crea un private scope = 5
, porque se encuentra inmediatamente después de la definición invocada. La estructura es closure
. Observe los corchetes function(){}()
después de la definición.
Esto hace que sea posible utilizarlo para la creación de objetos con revelando el patrón del módulo .
El truco es crear un alcance y devolver un objeto, que tenga acceso a este alcance 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, ()
), que a su vez tienen acceso a las variables "privadas" publicSetName
.
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. Uno 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.