Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

  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);
      }
  }


I understand the scoping issue here, but the recursive solution is just all around better:

  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.


You can make the recursive solution work without any delay:

  function countdown(n) {
      if(n >= 0) {
          alert(n);
          setTimeout(function() {countdown(n-1);}, 1000);
      }
  }


A slightly different version:

  function countdown (num) {
        for (var i = 0; i <= num; i += 1) {
            setTimeout(function (i) {
		return function(){ alert(num - i); }
            }(i), i * 1000);
        }
  }

  countdown(5);


cheater way:

alert(num--);

LoL.


Just curious about your wording. Why do you say this is the cheater way? It might stop working for large values of num where the anonymous function scheduled by the setTimeout begins executing before the for loop finishes. But it's certainly valid for a particular range of values.

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.


It's cheating because the point of the "challenge" is to see if you understand how scope works in Javascript — particularly with loops and closures, which confuse a lot of people — and how to use it properly. This "cheating" solution simply sidesteps the whole question by having the closures mutate a variable that the rest of the function doesn't touch.

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.


That depends on how the setTimeout() actually schedules things in the JavaScript engine. Recall that JavaScript is (before Chrome and worker threads appeared) traditionally single threaded - normally, even when you say setTimeout(fn, 0) - it's just putting your fn()'s execution at the end of the run loop - or whatever the scheduler calls its list of things to do. So, even though your current execution slice in the run loop may take like 1 minute, your fn() will still not execute until you're done what you're currently doing.


1.7:

  function countdown (num) {
      for (var i = 0; i <= num; i += 1) {
          let (j = num - i){
              setTimeout(function () {
                  alert(j);
              }, i * 1000);
          }
      }
  }


Don't answer challenge questions, bro


If Dropbox doesn't want their questions answered, they shouldn't harangue people for up-votes.


lol I guess so




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: