JavaScript Closure Scope

4

Stavo leggendo la sezione "Chiusure" del tutorial JavaScript di w3schools e non capisco come funziona l'ultimo esempio.

link

L'obiettivo è creare una variabile "privata" counter che possa essere modificata solo dalla funzione add . Ecco il codice:

<!DOCTYPE html>
<html>
<body>

<p>Counting with a local variable.</p>

<button type="button" onclick="myFunction()">Count!</button>

<p id="demo">0</p>

<script>
var add = (function  outer() {
    var counter = 0;
    return function inner() {return counter += 1;}
})();

function myFunction(){
    document.getElementById("demo").innerHTML = add();
}
</script>

</body>
</html>

Ho modificato le due funzioni anonime e le ho denominate outer e inner in modo che possano essere più facilmente referenziate. Ecco un link del codice in azione:

link

Quindi inizialmente la variabile add è assegnata a un'espressione di funzione autoinvocante. Ciò eseguirà la funzione outer una volta e imposterà counter su 0. Quando si fa clic sul pulsante, viene chiamato myFunction e questo inserisce il valore restituito della funzione add , il valore counter aggiornato, all'interno del tag p. Pertanto, facendo clic sul pulsante, il valore della variabile counter aumenta di 1 ogni evento on-click del pulsante. Non capisco come il valore del valore counter sia influenzato dalle funzioni outer e inner . Questo è il modo in cui l'ho (a torto) capito:

Quando la funzione add viene chiamata dalla funzione myFunction (su un evento onclick del pulsante), prima la funzione outer imposterà la variabile counter su 0 dalla seguente istruzione:

var counter = 0;

Intuitivamente penserei che il valore di ritorno della funzione add invocherebbe la funzione inner (specialmente perché posso vedere questo codice funziona) ma non capisco come. Questa è una domanda che ho. Se lo accetto, la funzione inner incrementerebbe la variabile counter di 1. Riesco a vedere come questo abbia senso fare clic sul pulsante che chiama la funzione myFunction una volta. Per la seconda volta che si fa clic sul pulsante non capisco come non si resetta. Sento che prima del secondo clic la variabile counter è 1 e quindi sul clic la funzione outer reimposta la variabile counter su 0 con questa riga di nuovo:

var counter = 0;

e quindi viene invocata la funzione inner . Poiché la funzione inner è nidificata nella funzione outer , è nel campo di applicazione accedere alla variabile counter e quindi aumentarla da 0 a 1. Cosa non sto capendo di questo?

Sento che potrei non capire come funziona l'istruzione return su una funzione, ma non ne sono sicuro. La variabile add è solo la funzione inner solo perché è ciò che viene restituito? E come viene richiamato se si trova all'interno di un'istruzione return ? Non capisco come var counter = 0; non venga eseguito ad ogni clic del pulsante quando viene richiamato myFunction .

Ho pensato che myFunction invochi la funzione add e che esegua la funzione outer , che esegue var counter = 0; e quindi la funzione inner viene restituita e invocata e aumenta la variabile counter .

Non capisco se restituire una funzione invocherebbe anche la funzione. Inoltre, non so se la creazione e l'assegnazione della variabile add abbiano avuto qualcosa a che fare con il modo in cui funziona. All'inizio non lo pensavo, ma chi lo sa? Non lo capisco, quindi tutto è possibile per me adesso.

    
posta drj30026abanba 10.12.2015 - 06:12
fonte

3 risposte

4

I don't get how var counter = 0; is not executed on every click of the button when myFunction is invoked.

Perché il codice

var add = (function  outer() {
    var counter = 0;
    return function inner() {return counter += 1;}
})();

esegue solo una volta. Restituisce una funzione immediata, memorizzandola nella variabile add , che successivamente assegnerai a qualcos'altro (usando = Add() ). Si noti la coppia finale di parentesi? Questo è ciò che causa la funzione esterna da eseguire immediatamente, una volta.

Quando viene assegnata la funzione nella variabile add , restituisce la funzione interna. Quella funzione interna è ciò che viene eseguito quando myFunction viene eseguito.

L'unica altra cosa che devi sapere è che la funzione interna ha accesso alla variabile counter nella funzione esterna, a causa della chiusura.

    
risposta data 10.12.2015 - 06:32
fonte
2

Sei confuso perché pensi che aggiungere sia:

var add = (function  outer() {
             var counter = 0;
             return function inner() {return counter += 1;}
           })();

ma in realtà aggiunge è:

add= function inner() {return counter += 1;}

perché questa funzione è ciò che la funzione di autoesecuzione esterna sta ritornando e che è stata assegnata per aggiungere.

La funzione esterna viene eseguita una sola volta (quando restituisce la funzione interna) e la variabile "contatore" inizializzata su 0.

La funzione figlio può accedere alla variabile della funzione genitore, e ogni volta che chiamiamo aggiungi, incrementa semplicemente "contatore" di 1.

    
risposta data 10.12.2015 - 22:04
fonte
1

aggiungi è in possesso di un riferimento alla funzione interna , ovvero funzione restituita dalla funzione esterna .

Chiusure è quando una funzione ricorda è il suo scope lessicale anche quando viene invocato dall'esterno scope lessicale.

Quindi inner ricorda il suo ambito e quindi in grado di accedere alla variabile counter . Pertanto, il suo inaccessibile esterno direttamente e agisce come privato . Ma aggiungi o interiore puoi manipolarlo.

Non appena fai riferimento aggiungi a un altro tipo l'ambito in cui si trova il contatore ottiene Garbage Collection e ottiene perso.

Ti consiglio di leggere libri di kyle simpson www.ydkjs.eu /

    
risposta data 10.12.2015 - 11:06
fonte

Leggi altre domande sui tag