Desvendando Closure Javascript
Tags: javascript
Published: 2023-04-12 16:09:23


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/x1v2hk2fe25tji3q4rhe.jpg)
Olá pessoas, bora falar um pouco sobre Closure Javascript, o que são? Do que se alimentam? E como usá-las? 🤔

Se você já ouviu falar, mas nunca entendeu direito o que é, ou se você é novo no mundo do JavaScript, bora mergulhar nesse tópico e aprender o que são closures, para que servem e como podemos tirar proveito deles em nossos projetos.

### Afinal, o que são? 

São funções canibais que se alimentam de outras 🤪 ... Brincadeiras a parte, vamos a definição técnica disponível no MDN:

> Uma closure é a combinação de uma função com as referências ao estado que a circunda (o ambiente léxico). Em outras palavras, uma closure lhe dá acesso ao escopo de uma função externa a partir de uma função interna - MDN Web Docs.

Então uma closure é uma função que tem acesso ao escopo de uma função externa, mesmo depois que a função externa tenha sido executada e encerrada. Isso significa que a closure pode "lembrar" e acessar variáveis e argumentos de sua função externa, mesmo que essa função já tenha sido finalizada. Legal, né?

Resumindo, nada mais é que funções que se apropriam do contexto de outras funções, no caso, funções definidas dentro do escopo de uma outra função e por isso possui acesso a variáveis e argumentos da função pai, mesmo que essa função já tenha sido finalizada. (diz aí se não são canibais 😶) 

Vamos a um exemplo:

```javascript
function createAdder(X) {
  return function(Y) {
    return X + Y;
  }
}

const addFive = createAdder(5);
console.log(addFive(10)); // Output: 15
```

Olhando esse código pela primeira vez pode parecer confuso, afinal de contas, o que uma função está fazendo dentro da outra? E gente, pra quê raios eu preciso retornar a função que eu declarei lá dentro? 🤯 ... Calma pessoal, prometo que tentarei explicar da melhor forma possível, bora lá.

Neste exemplo, `createAdder` é uma função que recebe um número `X` como argumento e retorna uma nova função que soma `X `com um segundo argumento `Y`. Então, criamos uma nova função `addFive` usando `createAdder(5)`. Essa nova função recebe um número `Y` como argumento e retorna a soma de `X + Y`. Quando chamamos `addFive(10)`, a função interna usa a referência a `X` mantida em sua closure para somar `X = 5` com `Y = 10`, retornando 15.

Observe que, mesmo que a função `createAdder` tenha concluído sua execução, a função interna retornada ainda tem acesso à variável `X` definida no escopo da função externa. Isso ocorre porque a função interna é uma closure que "lembra" o ambiente em que foi criada, incluindo todas as variáveis e funções disponíveis naquele ambiente.

### Tá, mas pra que isso serve? 😐

Além das utilidades que já mencionamos, closures podem ajudar a deixar seu código mais modular e organizado. Elas permitem que você crie funções com comportamentos específicos sem ter que duplicar código, e também ajudam a manter a privacidade de variáveis que não devem ser acessadas diretamente.

Por exemplo, vamos supor que você esteja criando um aplicativo de login com JavaScript e queira criar uma função que verifique se o nome de usuário e a senha estão corretos. Você pode criar uma função de verificação interna que mantém referências às credenciais do usuário como uma closure, impedindo que outras partes do código acessem essas credenciais diretamente:


```javascript
function createLoginChecker(username, password) {
  return function() {
    return username === "admin" && password === "1234";
  }
}

const checkLogin = createLoginChecker("admin", "1234")
console.log(checkLogin()); // Output: true
```

Observe que a função `createLoginChecker` retorna uma função interna que verifica se o nome de usuário e a senha correspondem às credenciais armazenadas em suas variáveis. A função interna é uma closure que "lembra" as credenciais do usuário e as verifica toda vez que a função é chamada. Isso permite que você crie funções privadas que não podem ser acessadas por outras partes do código.

Outra vantagem das closures é que elas podem ser usadas para criar funções que retêm estados. Por exemplo, suponha que você esteja criando um aplicativo que deve rastrear quantas vezes um usuário clicou em um botão. Você pode criar uma função que retém o estado do contador interno como uma closure:

```javascript
function createClickCounter() {
  let count = 0;
  return function() {
    count++;
    console.log(`Button clicked ${count} times`);
  }
}

const clickHandler = createClickCounter();

// Chamando a função 3 vezes
clickHandler(); // Output: Button clicked 1 times
clickHandler(); // Output: Button clicked 2 times
clickHandler(); // Output: Button clicked 3 times
```

Neste exemplo, a função `createClickCounter` retorna uma função interna que mantém o estado do contador `count`. Cada vez que a função interna é chamada, ela incrementa o contador e registra uma mensagem no console. A closure permite que a função interna mantenha o estado do contador entre as chamadas, permitindo que você rastreie quantas vezes o botão foi clicado.

### Ok, mas onde posso ver isso sendo utilizado mundo a fora? 

Legal até agora apresentamos exemplos ficticios, mas que tal olhar algum framework famoso que utiliza de closures? ... Aleatoriamente peguei um exemplo do nosso querido ReactJs de uma das funções mais populares `useState`.

```javascript
export function useState<S>(
  initialState: (() => S) | S,
): [S, Dispatch<BasicStateAction<S>>] {
  const dispatcher = resolveDispatcher();
  return dispatcher.useState(initialState);
}
```
Font - [ReactJs](https://github.com/facebook/react/blob/main/packages/react/src/ReactHooks.js#L99)

### OK, mas useState não é uma Closure 🤨

A função `useState` não é considerada um closure por si só, isso é um fato, porém ela pode retornar uma closure como resultado da chamada da função `useState` retornada pelo `dispatcher`. (te peguei nessa heimmm 😏) 

Ela é usada para criar um estado interno em componentes React. A implementação da função usa um closure para armazenar o valor atual do estado, bem como uma função para atualizá-lo. A função retornada por `useState` é uma closure que pode ser usada para atualizar o valor do estado interno.

Veja, ao chamar a função `useState` do `dispatcher`, que é retornada pela função `useState` do módulo React, uma closure é criada e ela captura o valor atual do estado e a função para atualizar o estado. Essa closure é retornada pelo `useState` do módulo React como o primeiro elemento do array retornado. A closure é uma função que tem acesso à variável `state` e à função `setState` definida dentro do escopo da função `useState`.

Bora para o exemplo:

```javascript
function Counter() {
  const [count, setCount] = useState(0);

  function handleClick() {
    setCount(count + 1);
  }

  return (
    <div>
      <p>You clicked {count} times</p>
      <button onClick={handleClick}>
        Click me
      </button>
    </div>
  );
}
```

Observe que a função `useState` é chamada com o valor inicial de 0, e retorna uma closure que captura o valor atual de count e a função `setCount`. A closure é atribuída a `count` e `setCount`, permitindo que a função `handleClick` atualize o valor de count usando a função de atualização retornada pela closure.

Dessa forma, a função `useState` retorna uma closure que permite que o estado seja atualizado através da função de atualização capturada pela closure. A closure é criada dentro da função `useState`, e captura o valor atual do estado e a função para atualizá-lo, permitindo que a closure tenha acesso ao escopo em que foi criada e possa atualizar o estado de forma segura.


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/zlwt0r60ddj1bacqxefm.gif)

### Finalmente, bora pro resumo

Na prática o que uma Closure faz é criar uma associação de informações com uma função que trabalha essas informações.
Apesar de estar ligada com programação funcional, isso tem também a ver com paradigma de orientação a objeto, onde as informações e métodos trabalham juntos, com isso você consegue explorar o escopo e o contexto das funções, isso deixa ainda mais claro como aplicar alguns design patterns como Strategy e a Inversão de dependência, além de criação de eventos e callbacks. 

E aí, curtiu aprender sobre closures? Espero que sim! Agora que você sabe o que são closures, para que servem e como utilizá-las, é hora de colocar esse conhecimento em prática nos seus projetos. Boa sorte e até a próxima. 🤗