Entenda closures finalmente

3 minuto(s) de leitura

Hoje vou apresentar um conceito que permeia todo código Javascript. Apesar de aparentar complexo à primeira vista, vemos que ele é bem simples depois que o entendemos.

A primeira coisa que precisamos entender é que toda função em Javascript é uma closure. Isso porque uma closure nada mais é que uma função que guarda uma referência de cada variável definida fora do seu escopo. Veja um exemplo:

var nome = "João",
    idade = 30

function imprimeDados() {
  console.log(nome + " " + idade)
}

imprimeDados()

Mas isso é apenas uma função que acessa varíaveis globais!? Exatamente. Closures não são nada muito além disso. No entanto, uma closure só possui acesso a variáveis declaradas fora do seu escopo, mas não dentro de funções definidas no seu próprio escopo.

image-center

Como pode ser visto na imagem, cada closure tem acesso ao seu próprio escopo e a todos os de fora. Mas uma outra característica interessante das closure é a possibilidade de continuar referenciando variáveis de funções que já terminaram. Vamos com mais um exemplo:

Supondo que nós precisássemos de uma função que a cada vez que é executada, retorna um contador incrementado em 1. Como poderiamos fazer isso?

A primeira forma é com uma varíavel global:

var cont = 0

function somaUm () {
  return ++cont
}

somaUm() // 1
somaUm() // 2
somaUm() // 3

O problema com essa solução é que deixamos a variável cont disponível para ser modificada. Colocar a variável dentro da função não funcionaria, pois toda hora ela seria declarada com valor 0. O ideal é que pudéssemos incrementar uma variável que não pode ser acessada de nenhum lugar fora da função. É ai que entra o bom uso de uma closure.

Utilizando funções anônimas imediatamente invocadas junto com uma closure, podemos fazer exatamente o que queremos:

var somaUm = (function () {
  var cont = 0

  return function () {
    return ++cont
  }

})()

somaUm() // 1
somaUm() // 2
somaUm() // 3

Aqui acontecem duas mágicas muito interessantes. Primeiro, criamos uma função anônima que é invocada assim que é criada. Se você não entende bem esse conceito de função imediatamente invocada, dê uma olhada aqui! Essa função retorna uma nova função (que é uma closure), que sempre retorna a variável da função anônima depois de incrementá-la.

Agora perceba que interessante, a variável que a função somaUm incrementa é a variável cont da função anônima que foi executada apenas no início. Dessa forma, apenas a somaUm tem acesso a ela.

Se ela foi executada apenas no início, como essa variável pode ainda continuar existindo? Se sabemos que variáveis locais só existem enquanto a função estiver sendo executada?

Com closure, todas as variáveis que ela referenciou continuam existindo enquanto ela também existir. Todas as variáveis da função anônima que foi executada no início vão continuar na memória do computador enquanto a closure que a referenciou puder ser chamada.

O que esse código faz na prática é criar uma variável privada, semelhante ao uso da keyword private do Java.

Se esse exemplo ainda ficou um pouco obscuro pra você, não se preocupe! Entender completamente esses conceitos no Javascript são um pouco complicados mesmo. Mas a continuidade nos estudos dos fundamentos da linguagem vai fazer com que você gradualmente se familiarize com todos os conceitos.

Se tiver alguma sugestão ou dúvida, deixe um comentário aqui. Vou ficar muito feliz de saber o que você achou desse artigo.

Ate mais!

Deixe um comentário