Treinamento Técnicas de Invasão

Como funcionam Closures em JavaScript

mm

Ramos de Souza Janones

Janones, é um empreendedor brasileiro apaixonado por empreendedorismo e tecnologia. Ao longo dos anos trabalhando com o desenvolvimento de softwares desktop desde a linguagem Clipper, passando pelo Delphi e atualmente com Java.

Optou pela formação de Publicidade e Marketing por sua segunda empresa de tecnologia ter participado do "boom" da internet nos anos 90 e na procura de melhorar seus conhecimentos em negócios.

Em razão da principal formação e profundos conhecimentos em programação e banco de dados, é capaz de realizar o desenvolvimento de aplicativos web, desktop e mobile com maior criatividade e inovação que profissionais de desenvolvimento com uma formação única e mais especifica, dedicada somente ao desenvolvimento de softwares.

Com toda sua experiência com empresas de software, sua formação e paixão por negócios escreveu o livro "Marketing para Empresas e Profissionais de Software", publicado pela editora carioca Ciência Moderna em 2012. Além de outros livros sobre programação.
mm

Closure (“clausura” em português, mas esse termo é raramente utilizado), se refere à forma como funções definidas dentro de um “contexto léxico” (i.e. o corpo de uma função, um bloco, um arquivo fonte) acessam variáveis definidas nesse contexto.

Em JavaScript, apenas funções definem um novo contexto léxico (outras linguagens têm regras diferentes – algumas sequer suportam o conceito de closure):

E cada novo contexto criado dentro (inner) de um contexto já existente tem acesso a todas as variáveis definidas no “de fora” (outer):

 

 

É importante observar que não importa quando a função interna irá executar, nem qual o valor as variáveis externas tinham no momento em que o objeto função foi criado (em contraste com a definição da função, que é em tempo de compilação/interpretação). O que importa é que ambas compartilham a mesma variável, e escritas de um lado refletirão nas leituras do outro e vice-versa.

Pitfalls

Um exemplo de erro comum envolvendo closures é a criação de uma função dentro de um bloco for:

Esse código não funciona como esperado, uma vez que a variável i utilizada pela função anônima é o mesmo i do contexto externo – o que significa que quando o i externo muda, o valor que a função interna vai acessar é diferente. No final, i será igual a elementos.length (ex.: 10), de modo que clicar em qualquer elemento sempre imprimirá “Esse é o elemento 10”.

Uma possível solução para esse problema é a criação de um novo contexto léxico que “capture” o valor daquela variável no momento desejado:

 

Dessa forma, o i parâmetro da função não é o mesmo i usado pelo laço for – e ele possui o valor que a variável tinha no momento da execução.

Utilidade

Existem muitas vantagens em se usar closures, como exemplificado na resposta do @Jordão (que demonstra um meio de se implementar currying). Um outro exemplo seria simular variáveis privadas – algo que não é normalmente suportado pela linguagem JavaScript:

 

Note que, como não existe nenhuma referência direta para privado, esse objeto não pode ser manipulado diretamente (apenas indiretamente por meio de foo e bar). Mas como foo e barforam criados dentro do contexto léxico do construtor, elas têm acesso às variáveis locals do mesmo, podendo acessá-las normalmente.

Um outro exemplo “clássico” é o Accumulator Generator, citado num artigo do Paul Graham (em inglês) onde se discute o poder de expressividade relativa das diversas linguagens de programação. O requisito é simples:

Escreva uma função foo que recebe um número n e retorna uma função que recebe um número i, e retorna n incrementado de i.

Nota: (a) [o argumento] é um número, não um inteiro. (b) é incrementado de, não mais.

A solução proposta, com exemplos de uso:

 

Como os exemplos no final do artigo mostram, linguagens que não suportam closures acabam sendo muito mais varbosas (exigindo muito código para se fazer pouco), de modo que demoram mais para serem escritas, lidas, podem conter mais bugs (já que a probabilidade de bugs aumenta com a quantidade de linha de código), etc.

Compartilhe.

PinIt
Top
%d blogueiros gostam disto: