2

I am trying to build a timer with JavaScript. Here's my function:

var t;
function time(num){
    var buf = num;
    document.getElementById("test").innerHTML=buf;
    buf++;
    alert(buf + " " + num); //For troubleshooting
    t=setTimeout("time(buf)",1000);
}

If I run time(0), nothing happens to the part with ID="test". num always equals 0 and buf always equals 1 (from the alert function) every time the function is called.

I'm comfortable with Java and C, and I know this would work in those language. I know JavaScript is also a pass-by-value language, so why doesn't this timer work?

Also, why did nothing happen when I tried (and changed all the buf to num)

t=setTimeout("time(num)",1000);

I know there are other ways to create a timer, but I want to know why this method doesn't work. Thanks.

Veech
  • 1,397
  • 2
  • 12
  • 20
  • You may think this is recursion, but it actually isn't. `time()` gets called, it then calls `setTimeout()` and passes a string that will be executed later. Then, `time()` returns and some time later, `time()` is called again by the timer code. This isn't technically recursion. The first call to `time()` has finished before the second one happens. You're just scheduling the second call for some time in the future. – jfriend00 Jan 02 '12 at 06:41

2 Answers2

4

Avoid passing strings to setTimeout. When you do this the string is more or less executed as an eval, which is evil for many reasons. See this question for more information.

Instead, consider passing an anonymous function to setTimeout. This will make solving your problem trivial:

t = setTimeout(function() { time(buf); }, 1000);
Community
  • 1
  • 1
Adam Rackis
  • 82,527
  • 56
  • 270
  • 393
2

When you pass a string to setTimeout, it is evaluated when the time comes. In this case, when the time comes, there's no buf variable anymore and the code throws an error.

You should substitute the value yourself.

t = setTimeout("time(" + buf + ")",1000);

Or, better yet, pass a function instead of string

t = setTimeout(function() {
  time(buf);
}, 1000);
Sergio Tulentsev
  • 226,338
  • 43
  • 373
  • 367