javascript - property - title html span



O que é um uso prático para um encerramento em JavaScript? (14)

Eu estou trying meu melhor para envolver minha cabeça em torno do fechamento de JavaScript.

Eu entendo que, retornando uma função interna, ele terá acesso a qualquer variável definida em seu pai imediato.

Onde isso seria útil para mim? Talvez eu ainda não tenha percebido isso. A maioria dos exemplos que vi online não fornecem nenhum código do mundo real, apenas exemplos vagos.

Alguém pode me mostrar um uso real do mundo 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();

https://src-bin.com


Answer #1

Muito do código que escrevemos no JavaScript front-end é baseado em eventos - nós definimos algum comportamento, então o anexamos a um evento que é acionado pelo usuário (como um clique ou um pressionamento de tecla). Nosso código é geralmente anexado como um retorno de chamada: uma única função que é executada em resposta ao evento. size12, size14 e size16 agora são funções que redimensionarão o texto do corpo para 12, 14 e 16 pixels, respectivamente. Podemos anexá-los aos botões (neste caso, links) da seguinte forma:

function makeSizer(size) {
    return function() {
    document.body.style.fontSize = size + 'px';
    };
}

var size12 = makeSizer(12);
var size14 = makeSizer(14);
var size16 = makeSizer(16);

document.getElementById('size-12').onclick = size12;
document.getElementById('size-14').onclick = size14;
document.getElementById('size-16').onclick = size16;

Fiddle


Answer #2

Aqui eu tenho um exemplo simples de conceito de fechamento que podemos usar em nosso site de comércio eletrônico ou muitos outros também. Eu estou adicionando meu link jsfiddle com o exemplo. contém uma pequena lista de produtos de 3 itens e um contador de carrinho.

Jsfiddle

//Counter clouser implemented function;
var CartCouter = function(){
	var counter = 0;
  function changeCounter(val){
  	counter += val
  }
  return {
  	increment: function(){
    	changeCounter(1);
    },
    decrement: function(){
    changeCounter(-1);
    },
    value: function(){
    return counter;
    }
  }
}

var cartCount = CartCouter();
function updateCart(){
	document.getElementById('cartcount').innerHTML = cartCount.value();
  }

var productlist = document.getElementsByClassName('item');
for(var i = 0; i< productlist.length; i++){
	productlist[i].addEventListener('click',function(){
  	if(this.className.indexOf('selected')<0){
    		this.className += " selected";
        cartCount.increment();
        updateCart();
    } else{
    	this.className = this.className.replace("selected", "");
      cartCount.decrement();
      updateCart();
    }
  })
}
.productslist{
  padding:10px;
}
ul li{
  display: inline-block;
  padding: 5px;
  border: 1px solid #ddd;
  text-align: center;
  width: 25%;
  cursor: pointer;
}
.selected{
  background-color: #7CFEF0;
  color: #333;
}
.cartdiv{
  position: relative;
  float:right;
  padding: 5px;
  box-sizing: border-box;
  border: 1px solid #f1f1f1;
}
<div>
<h3>
Practical Use of JavaScript Closure consept/private variable.
</h3>
<div class="cartdiv">
    <span id="cartcount">0</span>
</div>
<div class="productslist">
    <ul >
    <li class="item">Product 1</li>
     <li class="item">Product 2</li>
     <li class="item">Product 3</li>
    </ul>

</div>
</div>



Answer #4

Esse tópico me ajudou imensamente a entender melhor como funcionam os encerramentos. Eu já fiz algumas experiências e criei este código bastante simples que pode ajudar outras pessoas a ver como os fechamentos podem ser usados ​​de uma maneira prática e como usar o fechamento em diferentes níveis para manter variáveis ​​similares a estáticas e / ou variáveis ​​globais sem risco de serem sobrescritas ou confundidas com variáveis ​​globais. O que isto faz é acompanhar os cliques dos botões, tanto a nível local para cada botão individual como a nível global, contando cada clique de botão, contribuindo para uma única figura. Note que não usei nenhuma variável global para fazer isso, o que é o ponto 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 sozinho.

<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>Closures on button presses</title>
<script type="text/javascript">

window.addEventListener("load" , function () {
    /*
    grab the function from the first closure,
    and assign to a temporary variable 
    this will set the totalButtonCount variable
    that is used to count the total of all button clicks

    */
    var buttonHandler = buttonsCount(); 

    /*
    using the result from the first closure (a function is returned) 
    assign and run the sub closure that carries the 
    individual variable for button count and assign to the click handlers 
    */
    document.getElementById("button1").addEventListener("click" , buttonHandler() );
    document.getElementById("button2").addEventListener("click" , buttonHandler() );
    document.getElementById("button3").addEventListener("click" , buttonHandler() );

    // Now that buttonHandler has served its purpose it can be deleted if needs be
    buttonHandler = null;
});



function buttonsCount() {
    /* 
        First closure level 
        - totalButtonCount acts as a sort of global counter to count any button presses
    */
    var totalButtonCount = 0;

    return  function () {
        //second closure level
        var myButtonCount = 0;

        return function (event) {
            //actual function that is called on the button click
            event.preventDefault();
            /*  
               increment the button counts.
               myButtonCount only exists in the scope that is 
               applied to each event handler, therefore acts 
               to count each button individually whereas because 
               of the first closure totalButtonCount exists at 
               the scope just outside, so maintains a sort 
               of static or global variable state 
            */

            totalButtonCount++;
            myButtonCount++;

            /* 
                do something with the values ... fairly pointless 
                but it shows that each button contributes to both 
                it's own variable and the outer variable in the 
                first closure 
            */
            console.log("Total button clicks: "+totalButtonCount);
            console.log("This button count: "+myButtonCount);
        }
    }
}

</script>
</head>

<body>
    <a href="#" id="button1">Button 1</a>
    <a href="#" id="button2">Button 2</a>
    <a href="#" id="button3">Button 3</a>
</body>
</html>

Answer #5

Eu sei que estou super atrasado em responder a esta pergunta, mas pode ajudar alguém ainda a procurar a resposta em 2018.

Os fechamentos de Javascript podem ser usados ​​para implementar a funcionalidade de aceleração e debounce em seu aplicativo.

Throttling :

A limitação coloca um limite como um 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:

const throttle = (func, limit) => {
  let isThrottling
  return function() {
    const args = arguments
    const context = this
    if (!isThrottling) {
      func.apply(context, args)
      isThrottling = true
      setTimeout(() => isThrottling = false, limit)
    }
  }
}

Debasting :

Depurar colocar um limite em uma função não pode ser chamado novamente até que um determinado período de tempo tenha passado sem ser chamado. Como em "executar esta função somente se 100 milissegundos tiverem passado sem que seja chamado."

Código:

const debounce = (func, delay) => {
  let debouncing
  return function() {
    const context = this
    const args = arguments
    clearTimeout(debouncing)
    debouncing = setTimeout(() => func.apply(context, args), delay)
  }
}

Como você pode ver, os fechamentos ajudaram na implementação de dois belos recursos que cada aplicativo da Web deve ter para fornecer uma funcionalidade de experiência de interface do usuário tranquila.

Espero que ajude alguém.


Answer #6

Eu usei closures para fazer coisas como:

a = (function () {
    var privatefunction = function () {
        alert('hello');
    }

    return {
        publicfunction : function () {
            privatefunction();
        }
    }
})();

Como você pode ver, a agora é um objeto, com uma função publicfunction método ( a.publicfunction() ) que chama privatefunction , que existe apenas dentro do fechamento. Você NÃO pode chamar a função privatefunction diretamente (ou seja, a.privatefunction() ), apenas a função publicfunction() .

É um exemplo mínimo, mas talvez você possa ver usos para isso? Usamos isso para impor métodos públicos / privados.


Answer #7

Na amostra dada, o valor da variável fechada 'contador' é protegido e pode ser alterado somente usando as funções dadas (incremento, decremento). porque está em um fechamento

var MyCounter= function (){
    var counter=0;
    return {
    	increment:function () {return counter += 1;},
        decrement:function () {return counter -= 1;},
        get:function () {return counter;}
    };
};

var x = MyCounter();
//or
var y = MyCounter();

alert(x.get());//0
alert(x.increment());//1
alert(x.increment());//2

alert(y.increment());//1
alert(x.get());// x is still 2


Answer #8

Na linguagem JavaScript (ou 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 consultem nomes de dias da semana por índice, mas você não deseja que eles possam modificar a matriz de nomes que você usa sob o capô.

var dateUtil = {
  weekdayShort: (function() {
    var days = ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'];
    return function(x) {
      if ((x != parseInt(x)) || (x < 1) || (x > 7)) {
        throw new Error("invalid weekday number");
      }
      return days[x - 1];
    };
  }())
};

Observe que o array days poderia ser simplesmente armazenado como uma propriedade do objeto dateUtil mas ficaria visível para os usuários do script e eles poderiam até mesmo alterá-lo, se quisessem, sem precisar do código-fonte. No entanto, uma vez que é delimitada pela função anônima que retorna a função de pesquisa de data, ela só é acessível pela função de pesquisa e, portanto, é agora à prova de falsificação.


Answer #9

O padrão de módulo JavaScript usa closures. Seu bom padrão permite que você tenha algo parecido "público" e "privado" vars.

var myNamespace = (function () {

  var myPrivateVar, myPrivateMethod;

  // A private counter variable
  myPrivateVar = 0;

  // A private function which logs any arguments
  myPrivateMethod = function( foo ) {
      console.log( foo );
  };

  return {

    // A public variable
    myPublicVar: "foo",

    // A public function utilizing privates
    myPublicFunction: function( bar ) {

      // Increment our private counter
      myPrivateVar++;

      // Call our private method using bar
      myPrivateMethod( bar );

    }
  };

})();

Answer #10

Os fechamentos são uma maneira útil de criar generators , uma sequência incrementada sob demanda:

    var foobar = function(i){var count = count || i; return function(){return ++count;}}

    baz = foobar(1);
    console.log("first call: " + baz()); //2
    console.log("second call: " + baz()); //3

As diferenças são resumidas da seguinte forma:

Anonymous functions                                    Defined functions

Cannot be used as a method                             Can be used as a method of an object

Exists only in the scope in which it is defined        Exists within the object it is defined in

Can only be called in the scope in which it is defined Can be called at any point in the code

Can be reassigned a new value or deleted               Cannot be deleted or changed

Referências


Answer #11

Referência: uso prático de fechamentos

Na prática, os encerramentos 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 ordenação de arrays que aceita como argumento a função de condição de classificação:

[1, 2, 3].sort(function (a, b) {
    ... // sort conditions
});

Mapeamento de funções como o método de mapa de matrizes que mapeia uma nova matriz pela condição do argumento funcional:

[1, 2, 3].map(function (element) {
   return element * 2;
}); // [2, 4, 6]

Geralmente, é conveniente implementar funções de pesquisa usando argumentos funcionais definindo condições quase ilimitadas para pesquisa:

 someCollection.find(function (element) {
        return element.someProperty == 'searchCondition';
    });

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:

[1, 2, 3].forEach(function (element) {
    if (element % 2 != 0) {
        alert(element);
    }
}); // 1, 3

Uma função é aplicada aos argumentos (para uma lista de argumentos - em aplicar e para argumentos posicionados - na chamada):

(function () {
  alert([].join.call(arguments, ';')); // 1;2;3
}).apply(this, [1, 2, 3]);

Chamadas diferidas:

var a = 10;
    setTimeout(function () {
      alert(a); // 10, after one second
    }, 1000);

Funções de retorno:

var x = 10;
// only for example
xmlHttpRequestObject.onreadystatechange = function () {
  // callback, which will be called deferral ,
  // when data will be ready;
  // variable "x" here is available,
  // regardless that context in which,
  // it was created already finished
  alert(x); // 10
};

Criação de um escopo encapsulado com o objetivo de ocultar objetos auxiliares:

var foo = {};
(function (object) {
  var x = 10;
  object.getX = function _getX() {
    return x;
  };
})(foo);
alert(foo.getX());// get closured "x" – 10

Answer #12

Se você está confortável com o conceito de instanciar uma classe no sentido orientado a objeto (ou seja, criar um objeto dessa classe), então você está próximo de entender os fechamentos.

Pense desta maneira: quando você instancia dois objetos Person, você sabe que a variável de membro da classe "Name" não é compartilhada entre as instâncias; cada objeto tem sua própria 'cópia'. Da mesma forma, quando você cria um fechamento, a variável livre ('calledCount' no seu exemplo acima) é vinculada à 'instância' da função.

Eu acho que seu salto conceitual é um pouco dificultado pelo fato de que toda função / fechamento retornado pela função warnUser (à parte: essa é uma função de ordem superior ) vincula 'calledCount' com o mesmo valor inicial (0), enquanto que ao criar closures é mais útil passar inicializadores diferentes para a função de ordem mais alta, como passar valores diferentes para o construtor de uma classe.

Então, suponha que quando 'calledCount' atingir um certo valor, você queira terminar a sessão do usuário; você pode querer valores diferentes para isso dependendo se a requisição vem da rede local ou da grande internet ruim (sim, é um exemplo inventado). Para conseguir isso, você poderia passar valores iniciais diferentes para callCount em warnUser (ou seja, -3 ou 0?).

Parte do problema com a literatura é a nomenclatura usada para descrevê-los ("escopo léxico", "variáveis ​​livres"). Não se deixe enganar, fechamentos são mais simples do que parece ... prima facie ;-)


Answer #13

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 evento onclick do botão para atualizar a contagem da variável

<button onclick="updateClickCount()">click me</button>  

Agora pode haver muitas abordagens como:

1) Você poderia usar uma variável global e uma função para aumentar o contador :

var counter = 0;

function updateClickCount() {
    ++counter;
    // do something with counter
}

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:

function updateClickCount() {
    var counter = 0;
    ++counter;
    // do something with counter
}

Mas, ei! Toda vez que a função updateClickCount() é 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 pai countWrapper()

function countWrapper() {
    var counter = 0;
    function updateClickCount() {
    ++counter;
    // do something with counter
    }
    updateClickCount();    
    return counter; 
}

Isso poderia ter resolvido o dilema do contador, se você pudesse alcançar a função updateClickCount() do lado de fora e também precisa encontrar uma maneira de executar o counter = 0 apenas uma vez, não toda vez.

4) Encerramento para o resgate! (função de auto-invocação) :

 var updateClickCount=(function(){
    var counter=0;

    return function(){
     ++counter;
     // do something with counter
    }
})();

A função de auto-invocação só é executada uma vez. Define o counter como zero (0) e retorna uma expressão de função.

Desta forma, updateClickCount se torna uma função. A parte "maravilhosa" é que ela pode acessar o contador no escopo pai.

Isso é chamado de fechamento de JavaScript . Isso possibilita que uma função tenha variáveis ​​" privadas ".

O counter é protegido pelo escopo da função anônima e só pode ser alterado usando a função add!

Exemplo mais animado no encerramento:

  <script>
    var updateClickCount=(function(){
    var counter=0;

    return function(){
    ++counter;
     document.getElementById("spnCount").innerHTML=counter;
    }
  })();
</script>

<html>
 <button onclick="updateClickCount()">click me</button>
  <div> you've clicked 
    <span id="spnCount"> 0 </span> times!
 </div>
</html>

Answer #14

Uso de Fechamentos:

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 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 uma espécie 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 do que a própria função externa, se a função interna conseguir sobreviver além da duração da função externa. Um fechamento é criado quando a função interna é de alguma forma disponibilizada para qualquer escopo fora da função externa.

Exemplo:

<script>
var createPet = function(name) {
  var sex;

  return {
    setName: function(newName) {
      name = newName;
    },

    getName: function() {
      return name;
    },

    getSex: function() {
      return sex;
    },

    setSex: function(newSex) {
      if(typeof newSex == "string" && (newSex.toLowerCase() == "male" || newSex.toLowerCase() == "female")) {
        sex = newSex;
      }
    }
  }
}

var pet = createPet("Vivie");
console.log(pet.getName());                  // Vivie

console.log(pet.setName("Oliver"));   
console.log(pet.setSex("male"));
console.log(pet.getSex());                   // male
console.log(pet.getName());                  // Oliver
</script>

No código acima, a variável de nome 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 armazenamentos seguros para as funções internas. Eles mantêm dados "persistentes", mas seguros, para as funções internas trabalharem. As funções não precisam nem ser atribuídas a uma variável ou ter um nome. leia here para detalhes





terminology