I have the following function makeStopwatch
that I am trying to work through to better understand javascript closures:
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());
When I console.log
the calls to stopwatch1
and stopwatch2
I get 0
returned each time respectively.
As I understand the intended functionality of makeStopwatch
the variable elapsed
would be 0
if returned by the inner function stopwatch
. The inner function increase
increments the variable elapsed
. Then setInterval
calls increase
after a delay of 1 second. Finally, stopwatch
is returned again this time with the updated value which is expected to be 1
.
But this doesn't work because inside makeStopwatch
, the inner stopwatch
, increase
, and setInterval
functions are all in independent scopes of one another?
How can I revise this to work as I understand it so that elapsed
is incremented and that value is closed over and saved so that when I assign makeStopwatch
to variable stopwatch1
and call stopwatch1
the updated value is returned?
Answer
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.
So if were were to put all of the above code into the console, and then call console.log(stopwatch1())
sporadically, it will console.log the number of seconds since we created the stopwatch.
No comments:
Post a Comment