2015-07-11 15 views
6

Ho la seguente funzione makeStopwatch che sto cercando di lavorare attraverso per capire meglio javascript chiusure:Come accedere alle variabili in un altro ambito all'interno di una funzione usando la chiusura in javascript?

var makeStopwatch = function() { 
    var elapsed = 0; 
    var stopwatch = function() { 
    return elapsed; 
    }; 
    var increase = function() { 
    elapsed++; 
    }; 

    setInterval(increase, 1000); 
    return stopwatch; 
}; 

var stopwatch1 = makeStopwatch(); 
var stopwatch2 = makeStopwatch(); 

console.log(stopwatch1()); 
console.log(stopwatch2()); 

Quando ho console.log le chiamate stopwatch1 e stopwatch2 ottengo 0 tornati ogni volta rispettivamente.

Come ho capito la funzionalità prevista di makeStopwatch la variabile elapsed sarebbe 0 se restituita dalla funzione interna stopwatch. La funzione interna increase incrementa la variabile elapsed. Quindi setInterval chiama increase dopo un ritardo di 1 secondo. Infine, stopwatch viene restituito di nuovo questa volta con il valore aggiornato che dovrebbe essere 1.

Ma questo non funziona perché all'interno makeStopwatch, l'interno stopwatch, increase, e setInterval funzioni sono tutti in ambiti indipendenti l'uno dall'altro?

Come posso rivedere questo lavoro se ho capito bene in modo che elapsed viene incrementato e tale valore è chiuso più e salvato in modo che quando assegno makeStopwatch alla variabile stopwatch1 e chiamo stopwatch1 viene restituito il valore aggiornato?

+0

Il tuo codice funziona. Inoltre, CodeSchool? (Ho inserito il tuo codice esattamente come ce l'hai nella console. Esegui 'console.log (stopwatch1())' più volte.) – ChadF

+2

Il codice come postato registrerà sempre 0 per entrambi, poiché console.log si verificherà entro 1 secondo del cronometro che si sta creando. Prova a racchiudere le due righe inferiori in un 'setTimeout (console.log (stopwatch1()), 2000);' 'setTimeout (console.log (stopwatch2()), 4000);' ad esempio per vedere che i cronometri sono effettivamente " correndo " –

+0

Immagino di essere confuso perché guardando il corpo della funzione" aumenta "e come" trascorso "è incrementato, oltre a prendere in considerazione ciò che fa un cronometro reale, mi aspetto che console.logs mostra che il cronometro sta davvero contando verso l'alto. – phizzy

risposta

3
var makeStopwatch = function() { 
    var elapsed = 0; 

    // THIS stopwatch function is referenced later 
    var stopwatch = function() { 
    return elapsed; 
    }; 

    var increase = function() { 
    elapsed++; 
    }; 
    // This setInterval will continue running and calling the increase function. 
    // we do not maintain access to it. 
    setInterval(increase, 1000); 

    // THIS returns the stopwatch function reference earlier. The only way 
    // we can interact with the closure variables are through this function. 
    return stopwatch; 
}; 

var stopwatch1 = makeStopwatch(); 
// This runs the makeStopwatch function. That function *RETURNS* the 
// inner stopwatch function that I emphasized above. 

console.log(stopwatch1()); 
// stopwatch1 is a reference to the inner stopwatch function. We no longer 
// have access to the elapsed variable or the function increase. However 
// the `setInterval` that is calling `increase` is still running. So every 
// 1000ms (1 second) we increment elapsed by 1. 

Quindi, se erano stati di mettere tutto il codice sopra nella console, e quindi chiamare console.log(stopwatch1()) sporadicamente, sarà console.log il numero di secondi da quando abbiamo creato il cronometro.

Problemi correlati