I was asked (by a friend) to build a timer (infinite one which writes a line every second), but without setInterval
.
I solved it with :
It may look like recursion, but setTimeout does not create recursion.
The way setTimeout works is that it returns immediately. So the call to k
ends immediately with its stack deallocated.
When the timeout actually happens and the call to go
happens again it is not from the point of the previous call to k
but from the global scope*.
* Note: I'm not using the strict meaning of scope as defined in ECMAScript spec here. What I mean is the call to k
will be made as if you have written it in a plain tag: that is to say, outside of any other function calls.
In your specific case, there is very little that's actually enclosed in the closure created by the k
function. The only significant closure is the reference to the arguments cb
and myId
. And even then it only lasts for approximately one second:
#1 function k(myId, cb) {
#2 setTimeout(function(){
#3 console.log(myId); // there is a closure here to myId
#4 cb(); // and another one for cb
#5
/* But at this point in the function, setTimeout ends
* and as the function returns, there are no remaining
* references to either "cb" or "myId" accessible
* anywhere else. Which means that the GC can immediately
* free them (though in reality the GC may run a bit later)
*/
#6 }, 1000); // So one second is roughly the longest the closure lasts
}
I should note that your code is fairly convoluted. It can be written simpler, and without using closures at all (minus the global variable i) if you simply write it like this:
// Simpler, does exactly the same thing:
var i = 0;
function go () {
console.log(i);
i++;
setTimeout(go, 1000); // callback
}
go();