2015-07-11 17 views
6

Mam następujących funkcji makeStopwatch że staram się działać poprzez lepsze zrozumienie zamknięć javascript:Jak uzyskać dostęp do zmiennych w innym zakresie wewnątrz funkcji przy użyciu zamknięcia w 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()); 

Kiedy console.log połączeń do stopwatch1 i stopwatch2 dostaję 0 wrócił za każdym razem odpowiednio.

Jak rozumiem zamierzoną funkcjonalność makeStopwatch zmienna elapsed byłaby 0, jeśli zwrócona przez funkcję wewnętrzną stopwatch. Wewnętrzna funkcja zwiększa wartość zmiennej elapsed. Następnie setInterval dzwoni po opóźnieniu o 1 sekundę. Ostatecznie, stopwatch jest ponownie zwracany tym razem ze zaktualizowaną wartością, która ma być 1.

Ale to nie działa, ponieważ wewnątrz makeStopwatch, wewnętrzna stopwatch, increase i setInterval funkcje są w niezależnych od siebie zakresów?

Jak mogę zmienić to działało jak rozumiem to tak, że elapsed jest zwiększany i wartość ta jest zamknięta nad i zapisywane tak, że kiedy przypisać makeStopwatch zmiennej stopwatch1 i nazywają stopwatch1 zaktualizowana wartość jest zwracana?

+0

Twój kod działa. Również CodeSchool? (Umieszczam twój kod dokładnie tak, jak masz go w konsoli.) Uruchom 'console.log (stopwatch1())' wiele razy.) – ChadF

+2

Kod jako wysłany zawsze będzie rejestrował 0 dla obu, ponieważ konsola.log pojawi się w ciągu 1 sekundy tworzonego stopera. Spróbuj owijać dolne dwie linie w 'setTimeout (console.log (stopwatch1()), 2000);' 'setTimeout (console.log (stopwatch2()), 4000)' 'na przykład aby zobaczyć, że stopery są rzeczywiście" działa " –

+0

Myślę, że jestem zdezorientowany, ponieważ patrząc na ciało funkcji" wzrost "i jak" upływ czasu "jest zwiększany, a także biorąc pod uwagę moje postrzeganie tego, co robi stoper w świecie rzeczywistym, spodziewam się, że console.logs pokazać, że stoper rzeczywiście liczy się w górę. – phizzy

Odpowiedz

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. 

Więc jeśli były były umieścić wszystkie wyżej kod do konsoli, a następnie zadzwonić console.log(stopwatch1()) sporadycznie, to console.log liczbę sekund od stworzyliśmy stoper.