O objetivo de closures
é simplesmente preservar o estado; daí o nome closure
- ele fecha sobre o estado. Para facilitar a explicação, usarei Javascript.
Normalmente você tem uma função
function sayHello(){
var txt="Hello";
return txt;
}
onde o escopo da (s) variável (s) está vinculado a essa função. Então, após a execução, a variável txt
sai do escopo. Não há como acessá-lo ou usá-lo após a conclusão da execução da função.
Os fechamentos são construtos de linguagem, que permitem - como dito anteriormente - preservar o estado das variáveis e prolongar o escopo.
Isso pode ser útil em diferentes casos. Um caso de uso é a construção de funções de ordem superior .
Em matemática e ciências da computação, uma função de ordem superior (também forma funcional, funcional ou functor) é uma função que executa pelo menos um dos seguintes procedimentos: 1
- assume uma ou mais funções como entrada
- gera uma função
Um exemplo simples, mas admitidamente não muito útil, é:
makeadder=function(a){
return function(b){
return a+b;
}
}
add5=makeadder(5);
console.log(add5(10));
Você define uma função makedadder
, que recebe um parâmetro como entrada e retorna uma função . Existe uma função externafunction(a){}
e uma interna function(b){}{}
. Além disso, você define (implicitamente) outra função add5
como resultado de chamar a função de ordem superior makeadder
. makeadder(5)
retorna uma função anônima ( interna ), que, por sua vez, recebe 1 parâmetro e retorna a soma do parâmetro da função externa e o parâmetro da função interna .
O truque é que, ao retornar a função interna , que faz a adição real, o escopo do parâmetro da função externa ( a
) é preservado. add5
lembra , que o parâmetro a
foi 5
.
Ou para mostrar um exemplo pelo menos de alguma forma ú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"))));
Outro caso de uso comum é a chamada expressão de função IIFE = chamada imediatamente. É muito comum em javascript falsificar variáveis de membros particulares. Isso é feito por meio de uma função, que cria um escopo privado = closure
, porque é imediatamente após a definição da invocação. A estrutura é function(){}()
. Observe os colchetes ()
após a definição. Isso torna possível usá-lo para criação de objetos com padrão de módulo revelador . O truque é criar um escopo e retornar um objeto, que tenha acesso a esse escopo após a execução do IIFE.
O exemplo de Addi é assim:
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" );
O objeto retornado tem referências a funções (por exemplo publicSetName
), que por sua vez têm acesso a variáveis "particulares" privateVar
.
Mas esses são casos de uso mais especiais para Javascript.
Que tarefa específica um programador executaria que poderia ser melhor atendida por um fechamento?
Há várias razões para isso. Pode-se dizer que isso é natural para ele, pois ele segue um paradigma funcional . Ou em Javascript: é mera necessidade contar com fechamentos para contornar algumas peculiaridades da linguagem.