Por que o fechamento é importante para JavaScript?

16

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?

TomCaps
fonte
3
Como o JavaScript é tratado como linguagem funcional de primeira classe e o C # é um idioma clássico de POO. Diferentes paradigmas, diferentes estilos de programação.
Raynos
1
Ter uma função de primeira classe faz do idioma um idioma funcional. PHP (desde 5.3), python ou D tem função de primeira classe. Você diria que eles são linguagens funcionais? Certamente que não, e javascript também.
deadalnix
1
@deadalnix JavaScript é uma linguagem com vários paradigmas. Ele suporta principalmente o paradigma OO processual, funcional e prototípico. Não é de forma alguma uma linguagem funcional pura , mas você pode facilmente escrever javascript no paradigma funcional sem dobrar a linguagem. Eu diria o mesmo de C # e python.
Raynos
3
@deadalnix, uma linguagem que permite definir um combinador em Y é uma linguagem funcional. Por definição.
SK-logic
1
@deadalnix: Suponho que tudo se resume à questão de quais abordagens são promovidas pelo idioma. Existem muitas estruturas e plataformas JavaScript (principalmente node.js e DOM (modelo de evento)) que dependem muito das funções de primeira ordem. O PHP possui os recursos que permitem o mesmo estilo de programação, mas se você der uma olhada na API padrão ou em muitas estruturas, verá que não está realmente no centro da linguagem.
back2dos

Respostas:

5

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.

deadalnix
fonte
9
Isso não é um fechamento. Você descreve a vantagem de usar funções para criar escopo local.
Raynos 30/06
2
um fechamento é apenas um fechamento se fechar sobre variáveis ​​livres. Obrigado também por me dizendo que eu não sei como JavaScript funciona :)
Raynos
2
em vez de me comprometer chamando-me iniciante, sinta-se à vontade para apresentar argumentos reais na sala de bate-papo do SO JavaScript . Essa discussão realmente não pertence aqui, mas discutirei alegremente seus equívocos no bate-papo do SO.
Raynos
1
Votado. JavaScript é bastante orientado a objetos. Não é apenas baseado em classe, mas essa funcionalidade é de autoria fácil. Possui funções de primeira classe, aproveita os fechamentos para torná-lo um ajuste natural para paradigmas fortemente direcionados a eventos, e uma das principais fontes de inspiração, segundo seu autor, Brendan Eich, era Scheme. Não tenho muita certeza do que você acha que é uma linguagem funcional, mas a parte engraçada é que você acha que a herança baseada em classe é de alguma forma crítica, e não mais necessária, quando você pode repassar funções e aplicá-las em novos contextos.
quer
2
-1 também. Isso não descreve fechamentos, descreve o escopo.
31413 Izkata
12

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 getValuee increasesão de fato encerramentos, encapsulando a variável value.

user281377
fonte
3
-1 "depende do fechamento" Isso é altamente subjetivo. Isso não.
Raynos
Raynos: gostaria de nos mostrar como criar e usar membros privados sem fechamento?
user281377
1
@ammoQ não existe algo privado em JavaScript. O que você quis dizer foi "porque a emulação clássica de JavaScript OO depende de fechamentos". OO JavaScript é um protótipo, que é um paradigma diferente. É uma boa resposta para a pergunta, porém, "Nós usamos fechamentos em JavaScript, porque não precisava imitar OO clássica"
Raynos
1
@keppla eu quis dizer "OO depende de fechamentos" é subjetivo. Você não precisa de fechamentos para OO.
Raynos
2
você está me expondo como a prostituta de representante que eu sou ... #
312877
4

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 eachmé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.

keppla
fonte
1
Por que não é um fechamento? console.logé definido em um escopo externo, assim consolecomo uma 'variável livre'. E, por que, na verdade, é um loop for, que não faz nada diferente, uma má prática?
keppla
@ Raynos: minha definição de fechamento é 'bloco que contém uma variável livre', não perde esse status, a variável livre passa a estar no escopo superior. Mas, para apoiar meu argumento, considere este método: pastie.org/2144689 . Por que isso deveria ser ruim?
30611 keppla #
Eu ainda acho que "fechar" dados globais é considerado trapaça. Concordo que o acesso a dados na cadeia de escopo é bom, é simplesmente uma boa prática minimizar esse acesso.
Raynos
Concordaram em minimizar o acesso
keppla
Deve-se notar que, com iteradores de matriz (forEach, map, reduce, etc), não há motivo para serem encerramentos, eles têm todo o estado passado diretamente para eles. Eu consideraria isso um anti padrão para que eles sejam fechamentos
Raynos
3

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 #.

RationalGeek
fonte
2

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.

Filip Dupanović
fonte
1
O que a digitação estática tem a ver com isso? Os fechamentos são ortogonais.