I just can't figure it out, and it is bugging me. (Guess I won't get the job...)
I just can't figure it out, and it is bugging me. (Guess I won't get the job...)
function countdown (num) {
for (var i = 0; i <= num; i += 1) {
var make_cb = function (n) {
return function () {alert(num - n)};
}
setTimeout(make_cb(i), i * 1000);
}
} function countdown(num) {
if(num < 0) {
return;
}
setTimeout(function() {
alert(num);
countdown(num - 1);
}, 1000);
}
Note: I'm aware that the dropbox version shows the first alert without any delay, whereas this waits a second before showing anything. This is slightly different behavior, but arguably acceptable. function countdown(n) {
if(n >= 0) {
alert(n);
setTimeout(function() {countdown(n-1);}, 1000);
}
} function countdown (num) {
for (var i = 0; i <= num; i += 1) {
setTimeout(function (i) {
return function(){ alert(num - i); }
}(i), i * 1000);
}
}
countdown(5);alert(num--);
LoL.
EDIT: On second thought, does anyone even know if the scenario I mentioned above is plausible? I changed the alerts to console.logs and I'm finding it pretty damn impossible to not get the expected results using the "cheater way" even for large values of num.
And no, I don't think the potential problem you see is much of a problem at all. The function will keep executing even if the timers fire. As long as the timeouts execute in order and the countdown function is able to queue them in less time than they take to execute, it will work.
function countdown (num) {
for (var i = 0; i <= num; i += 1) {
let (j = num - i){
setTimeout(function () {
alert(j);
}, i * 1000);
}
}
}Traditional closure closes over the current variable values of a frame environment at each creation of an inner function instance. A new frame environment is cloned for the function instance with all the current variable values sealed. That's why it's called a closure; it's closed, sealed, that no one has access to it except the particular function instance.
Javascript cheats in its closure implementation. It doesn't create a new frame environment for each inner function instance, instead just references back to the parent's frame environment. Thus all inner function instances share the same frame environment. Any code in the parent function or in any function instance modifying a variable will instantly affect all the function instances. Closure has lost its meaning in Javascript. It should be called Shareture.
>>> map(apply, [lambda:i for i in range(5)])
[4, 4, 4, 4, 4]
* (mapcar 'funcall (loop for i from 0 to 5 collect (lambda () i)))
(6 6 6 6 6 6)
It's just that the looping constructs don't introduce a new binding, but modify the existing one. >>> map(apply, [lambda j=i:j for i in range(5)])
[0, 1, 2, 3, 4]
* (mapcar 'funcall (loop for i from 0 to 5 collect (let ((j i)) (lambda () j))))
(0 1 2 3 4 5)Grokking what's going on here is one of the more important parts of using closures without introducing unexpected bugs.
Deleted comment