Closures
- #JavaScript
Uma closure trata-se de um tipo especial de objeto que combina duas coisas: a função e o ambiente onde a função foi criada. Este ambiente consiste quaisquer variáveis que estavam no escopo naquele momento que a função foi criada. As funções podem acessar variáveis fora do seu escopo por meio de closures. Closures são criadas toda vez que dada função é criada, ou seja, quando é definida uma função seu escopo local e externo formam o ambiente léxico daquela função.
function makeSum(){
let number = 3;
function sum(){
console.log(number + 2);
}
sum();
}
makeSum();
// 5
O exemplo acima temos uma função dentro de outra função, esse termo é conhecido como funções aninhadas. A função makeSum é definida, dentro dela é criada uma variável number que guarda o valor 3, em seguida é defina a função sum que imprime no console a soma da variável number mais 2. Logo abaixo é feita uma chamada a sum dentro da função makeSum. E por ultimo é feito uma uma chamada a makeSum, que abaixo é exibido 5 no console.
Para explicar como a função sum consegue utilizar a variável number fora do seu escopo é algo que envolve não só o conceito de closures. Quando a função sum é definida também é definido seu ambiente léxico e ambos formam uma closure, para tornar a variável number visível para a função sum, o javascript utiliza o conceito chamado Lexical Scoping para fazer o parse da variável number. O Lexical Scoping localiza onde a variável number está declarada no código fonte para determinar onde ela é visível. Funções aninhadas tem acesso a variáveis fora de seu escopo.
function makeSum() {
let number = 3;
function sum() {
console.log(number + 2);
}
return sum;
}
let myFunc = makeSum();
myFunc();
// 5
Neste outro exemplo temos novamente funções aninhadas, o código acima segue a mesma lógica do primeiro exemplo, mas com algumas mudanças, a função makeSum agora retorna a função sum. Vamos para à parte onde makeSum é executada e seu retorno é armazenado na variável myFunc, myFunc agora guarda a função sum que foi retorna pela função makeSum, myFunc é executada e imprime no console o número 5.
Alguns podem não saber, mas em algumas linguagens de programação a variável de uma função só é visível até ela terminar de ser executada, então como a variável myFunc que guarda o retorno de makeSum consegui utilizar a variável number já que makeSum já terminou sua execução. A explicação é que quando makeSum é executada e retorna a função sum para a variável myFunc, myFunc agora guarda a referência de sum quando makeSum foi executada, ou seja, myFunc também guarda o ambiente léxico de sum quando foi definida dentro de makeSum durante a execução de makeSum.
Uma coisa interessante é que você pode executar funções aninhadas diretamente, basta colocar mais parênteses depois da função mãe. Antes dos hooks surgirem no React, o Redux utilizava funções aninhadas para conectar os reducers à estore da aplicação, mas com advento dos hooks, o Redux passou a utilizar hooks para fazer a conexão e obter os estados da store.
Abaixo esta um exemplo de executar a função makeSum do exemplo 2 diretamente.
function makeSum() {
let number = 3;
function sum() {
console.log(number + 2);
}
return sum;
}
makeSum()();
Fontes :
Livro: Eloquent javascript;
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Closures;