Estou tentando ao máximo para entender os fechamentos de JavaScript.
Eu entendo que, retornando uma função interna, ela terá acesso a qualquer variável definida em seu pai imediato.
Onde isso seria útil para mim? Talvez eu ainda não tenha pensado nisso. A maioria dos exemplos que eu vi online não fornece nenhum código do mundo real, apenas exemplos vagos.
Alguém pode me mostrar um uso real de um fechamento?
É este, por exemplo?
var warnUser = function (msg) {
var calledCount = 0;
return function() {
calledCount++;
alert(msg + '\nYou have been warned ' + calledCount + ' times.');
};
};
var warnForTamper = warnUser('You can not tamper with our HTML.');
warnForTamper();
warnForTamper();
Respostas:
Eu usei fechamentos para fazer coisas como:
Como você pode ver lá,
a
agora é um objeto, com um métodopublicfunction
(a.publicfunction()
) que chamaprivatefunction
, que só existe dentro do fechamento. Você NÃO pode ligarprivatefunction
diretamente (iea.privatefunction()
), apenaspublicfunction()
.É um exemplo mínimo, mas talvez você possa ver usos para ele? Usamos isso para aplicar métodos públicos / privados.
fonte
Suponha que você queira contar o número de vezes que o usuário clicou em um botão em uma página da web.
Para isso, você está acionando uma função no
onclick
evento do botão para atualizar a contagem da variávelAgora, pode haver muitas abordagens como:
1) Você pode usar uma variável global e uma função para aumentar o contador :
Mas, a armadilha é que qualquer script na página pode alterar o contador, sem chamar
updateClickCount()
.2) Agora, você pode estar pensando em declarar a variável dentro da função:
Mas, ei! Cada vez que a
updateClickCount()
função é chamada, o contador é definido como 1 novamente.3) Pensando em funções aninhadas ?
Funções aninhadas têm acesso ao escopo "acima" delas.
Neste exemplo, a função interna
updateClickCount()
tem acesso à variável de contador na função paicountWrapper()
Isso poderia ter resolvido o dilema do contador, se você pudesse alcançar a
updateClickCount()
função de fora e também precisar encontrar uma maneira de executarcounter = 0
apenas uma vez, nem sempre.4) Fechamento para o resgate! (função de chamada automática) :
A função de auto-chamada é executada apenas uma vez. Ele define
counter
zero (0) e retorna uma expressão de função.Desta forma,
updateClickCount
torna-se uma função. A parte "maravilhosa" é que ele pode acessar o contador no escopo pai.Isso é chamado de fechamento do JavaScript . Permite que uma função tenha " private variáveis " ".
O
counter
é protegido pelo escopo da função anônima e só pode ser alterado usando a função add!Exemplo mais animado sobre o encerramento:
Referência: https://www.w3schools.com/js/js_function_closures.asp
fonte
O exemplo que você dá é excelente. Os fechamentos são um mecanismo de abstração que permite separar as preocupações de maneira muito limpa. Seu exemplo é um caso de separação de instrumentação (contagem de chamadas) da semântica (uma API de relatório de erros). Outros usos incluem:
Passando o comportamento parametrizado para um algoritmo (programação clássica de ordem superior):
Simulando programação orientada a objetos:
Implementando controle de fluxo exótico, como manipulação de eventos do jQuery e APIs AJAX.
fonte
int
?) A última vez que verifiquei, o JavaScript era uma linguagem tipada por pato. Talvez você estivesse pensando em Java?Sei que estou super atrasado em responder a essa pergunta, mas isso pode ajudar quem ainda procura a resposta em 2018.
Os fechamentos Javascript podem ser usados para implementar a aceleração e o rebote funcionalidade de em seu aplicativo.
Limitação :
A limitação limita o número máximo de vezes que uma função pode ser chamada ao longo do tempo. Como em "execute esta função no máximo uma vez a cada 100 milissegundos".
Código:
Debouncing :
A conversão coloca um limite em uma função que não será chamada novamente até que um certo período de tempo tenha passado sem que ela seja chamada. Como em "execute esta função somente se 100 milissegundos se passaram sem que ela seja chamada".
Código:
Como você pode ver, os fechamentos ajudaram na implementação de dois belos recursos que todo aplicativo da Web deve ter para fornecer uma funcionalidade suave da experiência da interface do usuário.
Espero que ajude alguém.
fonte
Sim, esse é um bom exemplo de fechamento útil. A chamada para warnUser cria a
calledCount
variável em seu escopo e retorna uma função anônima que é armazenada nawarnForTamper
variável. Como ainda existe um fechamento usando a variável chamadaCount, ela não é excluída na saída da função, portanto, cada chamada para owarnForTamper()
aumentará a variável com escopo e alertará o valor.O problema mais comum que vejo no StackOverflow é onde alguém quer "atrasar" o uso de uma variável que é aumentada em cada loop, mas como a variável tem escopo definido, cada referência à variável seria após o encerramento do loop, resultando no estado final da variável:
Isso resultaria em todos os alertas mostrando o mesmo valor de
i
, o valor para o qual foi aumentado quando o loop terminou. A solução é criar um novo fechamento, um escopo separado para a variável. Isso pode ser feito usando uma função anônima executada instantaneamente, que recebe a variável e armazena seu estado como argumento:fonte
Na linguagem JavaScript (ou em qualquer ECMAScript), em particular, os fechamentos são úteis para ocultar a implementação da funcionalidade e, ao mesmo tempo, revelar a interface.
Por exemplo, imagine que você está escrevendo uma classe de métodos utilitários de data e deseja permitir que os usuários pesquisem nomes de dias da semana por índice, mas não deseja que eles possam modificar a matriz de nomes que você usa sob o capô.
Observe que a
days
matriz poderia simplesmente ser armazenada como uma propriedade dodateUtil
objeto, mas seria visível para os usuários do script e eles poderiam até alterá-lo se quisessem, sem precisar do seu código-fonte. No entanto, como é delimitada pela função anônima que retorna a função de pesquisa de data, ela só pode ser acessada pela função de pesquisa e, portanto, é à prova de violação.fonte
Há uma seção sobre fechamentos práticos na Mozilla Developer Network .
fonte
return function ()...
o código ainda funciona bem. O fechamento não é necessárioOutro uso comum para fechamentos é vincular
this
um método a um objeto específico, permitindo que ele seja chamado em outro lugar (como um manipulador de eventos).Sempre que um evento de remoção de mouse é acionado,
watcher.follow(evt)
é é chamado.Os fechamentos também são uma parte essencial das funções de ordem superior, permitindo o padrão muito comum de reescrever várias funções semelhantes como uma única função de ordem superior, parametrizando as partes diferentes. Como um exemplo abstrato,
torna-se
onde A e B não são unidades sintáticas, mas cadeias de código-fonte (não literais).
Consulte " Otimizando meu javascript com uma função " para um exemplo concreto.
fonte
Aqui, tenho uma saudação que quero dizer várias vezes. Se eu criar um fechamento, posso simplesmente chamar essa função para gravar a saudação. Se eu não criar o fechamento, tenho que passar meu nome sempre.
Sem fechamento ( https://jsfiddle.net/lukeschlangen/pw61qrow/3/ ):
Com um fechamento ( https://jsfiddle.net/lukeschlangen/Lb5cfve9/3/ ):
fonte
Se você se sente confortável com o conceito de instanciar uma classe no sentido orientado a objetos (por exemplo, para criar um objeto dessa classe), está próximo de entender os fechamentos.
Pense dessa maneira: quando você instancia dois objetos Person, sabe que a variável de membro da classe "Name" não é compartilhada entre instâncias; cada objeto tem sua própria 'cópia'. Da mesma forma, quando você cria um fechamento, a variável livre ('chamadaCount' no seu exemplo acima) é vinculada à 'instância' da função.
Eu acho que seu salto conceitual é um pouco dificultado pelo fato de que todas as funções / fechamentos retornados pela função warnUser (exceto: essa é uma função de ordem superior ) vinculam 'namedCount' com o mesmo valor inicial (0), embora muitas vezes ao criar closures é mais útil passar inicializadores diferentes para a função de ordem superior, como passar valores diferentes para o construtor de uma classe.
Portanto, suponha que quando 'namedCount' atingir um determinado valor que você deseja encerrar a sessão do usuário; você pode querer valores diferentes para isso, dependendo se a solicitação vem da rede local ou da grande e ruim Internet (sim, é um exemplo artificial). Para conseguir isso, você pode passar diferentes valores iniciais para chamado Count para warnUser (ou seja, -3 ou 0?).
Parte do problema da literatura é a nomenclatura usada para descrevê-los ("escopo lexical", "variáveis livres"). Não se deixe enganar, os fechamentos são mais simples do que pareceriam ... prima facie ;-)
fonte
Aqui eu tenho um exemplo simples de conceito de fechamento que podemos usar em nosso site de comércio eletrônico ou em muitos outros também. Estou adicionando meu link jsfiddle com o exemplo. Ele contém uma pequena lista de produtos com 3 itens e um contador de carrinho.
Jsfiddle
fonte
Uso de Fechos:
Os fechamentos são um dos recursos mais poderosos do JavaScript. O JavaScript permite o aninhamento de funções e concede à função interna acesso total a todas as variáveis e funções definidas dentro da função externa (e a todas as outras variáveis e funções às quais a função externa tem acesso). No entanto, a função externa não tem acesso às variáveis e funções definidas dentro da função interna. Isso fornece um tipo de segurança para as variáveis da função interna. Além disso, como a função interna tem acesso ao escopo da função externa, as variáveis e funções definidas na função externa viverão mais tempo que a própria função externa, se a função interna conseguir sobreviver além da vida útil da função externa.
Exemplo:
No código acima, a variável name da função externa é acessível para as funções internas e não há outra maneira de acessar as variáveis internas, exceto através das funções internas. As variáveis internas da função interna atuam como reservas seguras para as funções internas. Eles mantêm dados "persistentes", mas seguros, para as funções internas trabalharem. As funções nem precisam ser atribuídas a uma variável ou ter um nome. leia aqui para detalhes
fonte
Eu gosto do exemplo da fábrica de funções do Mozilla .
fonte
O padrão do módulo JavaScript usa fechamentos. Seu bom padrão permite que você tenha algo parecido com "público" e "privado".
fonte
Escrevi um artigo há algum tempo sobre como os fechamentos podem ser usados para simplificar o código de manipulação de eventos. Ele compara a manipulação de eventos do ASP.NET ao jQuery do lado do cliente.
http://www.hackification.com/2009/02/20/closures-simplify-event-handling-code/
fonte
Esse tópico me ajudou imensamente a entender melhor como funcionam os fechamentos. Desde então, fiz algumas experiências e criei esse código bastante simples que pode ajudar outras pessoas a ver como os fechamentos podem ser usados de maneira prática e como usar o fechamento em diferentes níveis para manter variáveis semelhantes a estática e / ou variáveis globais sem risco de serem substituídos ou confundidos com variáveis globais. O que isso faz é acompanhar os cliques no botão, tanto no nível local de cada botão individual quanto no nível global, contando cada clique do botão, contribuindo para uma única figura. Observe que não usei nenhuma variável global para fazer isso, que é o objetivo do exercício - ter um manipulador que possa ser aplicado a qualquer botão que também contribua para algo globalmente.
Por favor, especialistas, deixe-me saber se eu cometi alguma má prática aqui! Eu ainda estou aprendendo essas coisas.
fonte
Referência: Uso prático de tampas
Na prática, os fechamentos podem criar designs elegantes, permitindo a personalização de vários cálculos, chamadas adiadas, retornos de chamada, criação de escopo encapsulado etc.
Um exemplo do método de classificação de matrizes que aceita como argumento a função de condição de classificação:
Mapeando funcionais como o método map de matrizes que mapeia uma nova matriz pela condição do argumento funcional:
Muitas vezes, é conveniente implementar funções de pesquisa usando argumentos funcionais que definem condições quase ilimitadas para a pesquisa:
Além disso, podemos observar a aplicação de funcionais como, por exemplo, um método forEach que aplica uma função a uma matriz de elementos:
Uma função é aplicada aos argumentos (a uma lista de argumentos - em aplicar e a argumentos posicionados - em chamada):
Chamadas diferidas:
Funções de retorno de chamada:
Criação de um escopo encapsulado com a finalidade de ocultar objetos auxiliares:
fonte
Violino
fonte
Os fechamentos são uma maneira útil de criar geradores, uma sequência incrementada sob demanda:
As diferenças estão resumidas da seguinte forma:
Referências
fonte
Na amostra fornecida, o valor da variável fechada 'counter' é protegido e pode ser alterado apenas usando as funções fornecidas (incremento, decremento). porque está em um fechamento,
fonte
Explicando o uso prático de um Encerramento em JavaScript ---
Quando criamos uma função dentro de outra função, estamos criando um fechamento. Os fechamentos são poderosos porque são capazes de ler e manipular os dados de suas funções externas. Sempre que uma função é chamada, um novo escopo é criado para essa chamada. A variável local declarada dentro da função pertence a esse escopo e só pode ser acessada a partir dessa função. Quando a função termina a execução, o escopo geralmente é destruído.
Um exemplo simples de tal função é este:
No exemplo acima, a função buildName () declara uma saudação de variável local e a retorna. Cada chamada de função cria um novo escopo com uma nova variável local. Depois que a função é executada, não temos como nos referir a esse escopo novamente, portanto, é coletado como lixo.
Mas e quando temos um link para esse escopo?
Vejamos a próxima função:
A função sayName () deste exemplo é um fechamento. A função sayName () possui seu próprio escopo local (com variável bem-vinda) e também tem acesso ao escopo da função externa (anexa). Nesse caso, a saudação variável de buildName ().
Após a execução do buildName, o escopo não é destruído nesse caso. A função sayMyName () ainda tem acesso a ela, portanto não será coletada como lixo. No entanto, não há outra maneira de acessar dados do escopo externo, exceto o fechamento. O fechamento serve como porta de entrada entre o contexto global e o escopo externo.
fonte
Estou tentando aprender clousures e acho que o exemplo que criei é um caso de uso prático. Você pode executar o snippet e ver o resultado no console. temos dois usuários separados que possuem dados separados. Cada um deles pode ver o estado real e atualizá-lo.
fonte