A maior parte dos programadores de JavaScript usam o encerramento consciente ou inconscientemente. Mesmo que o façam inconscientemente, funciona bem na maioria dos casos. Mas o conhecimento do encerramento proporcionará um melhor controlo sobre o código ao utilizá-los. E outra razão para o encerramento da aprendizagem é que é a pergunta mais frequentemente feita na entrevista para os programadores de JavaScript.
Prerequisito:: Âmbito variável em JavaScript
Deixe ver e compreender o encerramento através de um exemplo.
Exemplo 1:
/p>
>/p>
function
foo()
{
var
b = 1;
function
inner(){
return
b;
}
return
inner;
}
var
get_func_inner = foo();
console.log(get_func_inner());
console.log(get_func_inner());
console.log(get_func_inner());
br>
Explicação:O interessante a notar aqui é da linha número 9 à linha número 12 . Na linha número 9, a execução da função foo() é feita e todo o corpo da função interna() é devolvido e armazenado em var get_func_inner, devido à linha 7 return inner.
p>P>Pomos a variável b que é definida na função foo() através da função interna(), uma vez que esta última preserva a cadeia de escopo da função de enclausuramento no momento da execução da função de enclausuramento i.e. a função interna conhece o valor de b através da sua cadeia de escopo.
Este é o fecho em acção que é a função interna pode ter acesso às variáveis da função externa, bem como a todas as variáveis globais.
Encerramento do código acima:
p>Para ver a variável e função encadernada dentro do encerramento podemos escrever como:
/p>
>br>>>/p>
console.dir(get_func_inner);
Eliminar:
br> Como podemos ver as variáveis dentro do fecho na secção de âmbito.
Definição de Fechamento:
Em linguagens de programação, os fechamentos (também fechamentos lexicais ou fechamentos de funções) são técnicas de implementação de encadernação lexical de nomes em linguagens com funções de primeira classe. Operacionalmente, um encerramento é um registo que armazena uma função juntamente com um ambiente: um mapeamento que associa cada variável livre da função (variáveis que são utilizadas localmente, mas definidas num âmbito envolvente) com o valor ou referência ao qual o nome estava vinculado quando o encerramento foi criado.
-Wikipedia
ou
Por outras palavras, o encerramento é criado quando uma função criança mantém o ambiente do âmbito dos pais mesmo depois de a função pai já ter executado
Agora vamos olhar para outro exemplo.
Exemplo 2:
/p>
>br>>/p>
/div>
function
foo(outer_arg) {
function
inner(inner_arg) {
return
outer_arg + inner_arg;
}
return
inner;
}
var
get_func_inner = foo(5);
console.log(get_func_inner(4));
console.log(get_func_inner(3));
br>>>/div>
Explicação: No exemplo acima, utilizámos uma função de parâmetro em vez de uma função por defeito. Nota: Mesmo quando terminamos com a execução de foo(5) podemos aceder à variável externa_arg a partir da função interna. E na execução da função interna produzimos a soma de outer_arg e inner_arg como desejado.
Output:
Agora vamos ver um exemplo de fecho dentro de um laço.
Neste exemplo iríamos armazenar uma função anónima em cada índice de um array.
Exemplo 3:
/p>
>br>>>/p>
/div>
function
outer()
{
var
arr = ;
var
i;
for
(i = 0; i < 4; i++)
{
arr =
function
() {
return
i; }
}
return
arr;
}
var
get_arr = outer();
console.log(get_arr());
console.log(get_arr());
console.log(get_arr());
console.log(get_arr());
>/div>
Eliminar:
Explicação: Adivinhou a resposta certa? No código acima, criámos quatro fechamentos que apontam para a variável i que é a variável local para a função externa. O fecho não se lembra do valor da variável que apenas aponta para a variável ou armazena a referência da variável e, portanto, retorna o valor actual. No código acima quando tentamos actualizar o valor da mesma é reflectido para todos porque o fecho armazena a referência.
Vejamos uma forma correcta de escrever o código acima de modo a obter valores diferentes de i em índices diferentes.
Exemplo 4:
/p>
>br>
function
outer()
{
function
create_Closure(val)
{
return
function
()
{
return
val;
}
}
var
arr = ;
var
i;
for
(i = 0; i < 4; i++)
{
arr = create_Closure(i);
}
return
arr;
}
var
get_arr = outer();
console.log(get_arr());
console.log(get_arr());
console.log(get_arr());
console.log(get_arr());
p>Eliminar:
br>Explicação: No código acima, estamos a actualizar o argumento da função create_Closure com cada chamada. Assim, obtemos valores diferentes de i em índices diferentes.
Nota: Pode ser ligeiramente difícil obter o conceito de encerramento de uma só vez, mas tente experimentar o encerramento em cenários diferentes como para criar getter/setter, callbacks e assim por diante.
Referência:
“Object Oriented JavaScript” de Stoyan Stefanov
Este artigo é contribuído por Sumit Ghosh. Se gosta de GeeksforGeeks e gostaria de contribuir, pode também escrever um artigo usando o contribute.geeksforgeeks.org ou enviar o seu artigo por correio para [email protected]. Veja o seu artigo que aparece na página principal do GeeksforGeeks e ajude outros Geeks.