A expressão lambda do C # também possui encerramentos, mas raramente é discutida pelas comunidades ou livros em C #. Vejo muito mais pessoas e livros sobre JavaScript falarem sobre seus fechamentos do que no mundo C #. Por que é que?
A expressão lambda do C # também possui encerramentos, mas raramente é discutida pelas comunidades ou livros em C #. Vejo muito mais pessoas e livros sobre JavaScript falarem sobre seus fechamentos do que no mundo C #. Por que é que?
Respostas:
Como o javascript não possui recursos como espaços para nome, você pode mexer facilmente com todos os tipos de objetos globais.
Portanto, é importante poder isolar algum código em seu próprio ambiente de execução. O fechamento é perfeito para isso.
Esse uso do fechamento não faz sentido em uma linguagem como C # onde você tem namespaces, classes e assim por diante para isolar o código e não colocar tudo no escopo global.
Uma prática muito comum para o código javascript está gravando assim:
(function(){
// Some code
})();
Como você pode ver, esta é uma declaração de função anônima, seguida imediatamente por sua execução. Assim, tudo o que é definido dentro da função é impossível de acessar de fora e você não estraga o escopo global. O contexto de execução dessa função permanecerá ativo enquanto algum código a usar, como funções aninhadas definidas nesse contexto, que você poderá transmitir como retorno de chamada ou qualquer outra coisa.
Javascript é uma linguagem muito diferente de c #. Não é orientado a objetos, é orientado a protótipo. Isso leva a práticas muito diferentes no final.
Enfim, os fechamentos são bons, então use-os, mesmo em C #!
EDIT: Depois de algumas discussões sobre o bate-papo do stackoverflow, acho que essa resposta precisa ser precisa.
A função no código de exemplo não é um fechamento. No entanto, essa função pode definir variáveis locais e funções aninhadas. Todas as funções aninhadas que usam essas variáveis locais são encerramentos.
Isso é útil para compartilhar alguns dados em um conjunto de funções sem alterar o escopo global. Este é o uso mais comum de fechamento em javascript.
O fechamento é muito mais poderoso do que apenas compartilhar alguns dados como este, mas sejamos realistas, a maioria dos programadores não sabe nada sobre programação funcional. Em C #, você usaria classe ou um espaço para nome para esse tipo de uso, mas o JS não fornece essa funcionalidade.
Você pode fazer muito mais com o fechamento do que apenas proteger o escopo global, mas é isso que você verá no código-fonte JS.
Provavelmente porque implementações populares da orientação a objetos do JavaScript dependem de fechamentos. Vejamos um exemplo simples:
function counter() {
var value = 0;
this.getValue = function() { return value; }
this.increase = function() { value++; }
}
var myCounter = new counter();
console.log(myCounter.getValue());
myCounter.increase();
console.log(myCounter.getValue());
Os métodos getValue
e increase
são de fato encerramentos, encapsulando a variável value
.
Porque muitas das bibliotecas que tornam o JavaScript 'suportável' as usam.
Dê uma olhada no JQuery , Prototype ou MooTools , apenas para citar três populares. Cada uma dessas bibliotecas fornece um each
método para suas coleções como a maneira preferida de iteração, que usa uma função de iterador. Essa função, ao acessar valores no escopo externo, será um fechamento:
[1,2,3].each(function(item) {
console.log(item);
});
E isso não pára por aí: retornos de chamada no Ajax, manipulação de eventos no Ext.js, etc, todos têm funções, e se você não quiser sobrecarregar seu código com 100eds de funções chamadas exatamente uma vez, os fechamentos são o caminho a seguir.
console.log
é definido em um escopo externo, assim console
como uma 'variável livre'. E, por que, na verdade, é um loop for, que não faz nada diferente, uma má prática?
Concordo com as outras respostas de que a codificação "boa" com JavaScript depende mais fortemente do fechamento. No entanto, além disso, provavelmente é apenas uma questão de quanto tempo o recurso existe em cada idioma. O JavaScript basicamente teve encerramentos desde suas primeiras implementações. O C #, por outro lado, só os possui desde o 3.0, lançado com o Visual Studio 2008.
Muitos programadores em C # que encontro ainda estão trabalhando em projetos 2.0. E mesmo que estejam trabalhando no 3.0 ou 4.0, eles ainda estão usando expressões 2.0. Eu amo fechamentos; espero que eles se tornem mais usados em C # à medida que o conceito se propaga entre os desenvolvedores de C #.
O principal motivo é que o C # é estaticamente digitado e as funções têm acesso apenas a um ambiente único e predeterminado, o que impede a utilidade dos fechamentos.
Em JavaScript, por outro lado, os fechamentos permitem que as funções se comportem como métodos quando acessadas como uma propriedade de objeto e, sendo objetos de primeira classe, elas também podem ser injetadas em diferentes ambientes, o que permite que as sub-rotinas operem em diferentes contextos.
Um dos motivos pelos quais tive que aprender sobre eles foi porque, quando você percorre os elementos DOM (ou qualquer coisa realmente), deseja "fechar" ou "encapsular" o escopo da variável. Como no exemplo publicado aqui: /programming/5606059/how-to-create-closure-in-loop-and-store-it-in-variable-for-later-execution