8

I am relatively novice to javascript. I have written a simple counter program that starts count down from 10 till it reaches 1.

  <script type="text/javascript">
    function countDown(secs) {
        var element = document.getElementById("status");
        element.innerHTML = "Please wait for "+secs+" seconds";
        if(secs < 1) {
            clearTimeout(timer);
            element.innerHTML = '<h2>Countdown Complete!</h2>';
            element.innerHTML += '<a href="#">Click here now</a>';
        }
        secs--;
 --->       **var timer = setTimeout('countDown('secs')',1000);**
    }
    </script>
    <div id="status"></div>
    <script type="text/javascript">countDown(10);</script>

Then I tried passing parameter as '+secs+' to the countDown function.

var timer = setTimeout('countDown('+secs+')',1000);

Above change works.

My question is why should I need to pass parameter as '+secs+' and NOT only 'secs' ? What difference does it make?

jahroy
  • 22,322
  • 9
  • 59
  • 108
v09
  • 840
  • 2
  • 12
  • 22

8 Answers8

12

use

var timer = setTimeout(function(){
        countDown(secs)
    },1000);

or

var timer = setTimeout('countDown('  + secs + ')',1000);

In your case the problem was your were using string concatenation with a variable without + sign (my second example) with will cause a syntactical error

Arun P Johny
  • 384,651
  • 66
  • 527
  • 531
9

Your first attempt is a synax error:

var timer = setTimeout('countDown('secs')',1000);

You're trying to pass a string to setTimeout (which is a bad idea to begin with), but you're not creating the string properly.

The single quotes around the word secs are not escaped, so you're actually passing the string literal countDown( followed by the variable secs, followed by the string literal ). Because there are no operators between the strings, this is invalid syntax.

However, when you use the + symbols, you're adding 3 strings together to create the method invocation you want (the + operator is used to concatenate strings in JavaScript):

'countDown(' + 'secs' + ')' ===  'countDown(secs)'

The three strings added together create a string that contains valid JavaScript, so it can be passed to the setTimeout() function.

Although you can pass a string to setTimeout(), the better approach is to pass a function reference.

This is typically done with an anonymous function like this:

setTimeout(function () {
    countDown(secs);
}, 1000);

If you don't need to pass a parameter, you can do this:

function countDown() {
    alert("10... 9... 8...");
}

setTimeout(countDown, 1000);

Note that when a function reference is specified as a variable, you do not use the () symbols. When you use parentheses after a function in JavaScript, the function is invoked.

jahroy
  • 22,322
  • 9
  • 59
  • 108
  • 1
    No problem. Glad to help. Just as an FYI, I always find the MDN documentation to be the best reference for JavaScript. So.... When I have a question about how _setTimeout()_ works, the first thing I always do is google ["_mdn javascript settimeout_"](https://developer.mozilla.org/en-US/docs/Web/API/window.setTimeout). – jahroy Jun 13 '13 at 06:41
  • Or rather `settimeout -w3schools` :) – Ja͢ck Jun 13 '13 at 06:53
5

an easy way to do it using setTimeout:

setTimeout(FunctionName,delay,arg1,arg2....);

In your case you can simply do like that:

setTimeout(countDown,1000,secs);

I suggest this link: http://javascript.info/settimeout-setinterval

senior
  • 2,196
  • 6
  • 36
  • 54
2

Aadit had the right idea. I needed to start multiple timeouts within a loop, and they all ended up with the variable set to the same value. Here is a fiddle illustrating why the only method that works well asynchronously is Aadit's.

http://jsfiddle.net/85fmwew4/

for(i=0;i<10;i++){
    setTimeout(function(){bad(i)}, 1000)    // bad for async
    setTimeout(good, 1000, i)               // good for async
}
1

Just write a closure to perform the decrement like so:

if (secs < 1) {
    element.innerHTML = '<h2>Countdown Complete!</h2>';
    element.innerHTML += '<a href="#">Click here now</a>';
} else {
    // wait 1 second
    setTimeout(function() {
        countDown(secs - 1); // decrement and run ourselves again
    }, 1000);
}

I've also removed the clearTimeout() in favour of a simple else condition.

Ja͢ck
  • 170,779
  • 38
  • 263
  • 309
1

The setTimeout function allows you to pass additional parameters to the function. Hence you can rewrite your code as follows:

var timer = setTimeout(countDown, 1000, secs);

It's supported in all major browsers except for some old versions of IE. See this question for more details: Why does Underscore.js have a delay function?

Community
  • 1
  • 1
Aadit M Shah
  • 72,912
  • 30
  • 168
  • 299
1

Now with recent javascript optimizations in modern browsers, you can simply do:

var timer = setTimeout( countDown( secs ) , 1000 );

Damilola Olowookere
  • 2,253
  • 2
  • 23
  • 33
0

This is the only thing that worked for me (passing variables to setTimeout in node.js):

setTimeout(function(teamNum,zeroBase,position) {
    spawnAI(roomIndex, 'scout', teamNum, position);
}, timeToSpawn,teamNum,zeroBase,position);
Chris Scott
  • 583
  • 1
  • 7
  • 23