When passing functions to a method, why does using an anonymous function container work and not just the original function?

StackOverflow https://stackoverflow.com/questions/20604129

Question

I'm new to JavaScript and was messing around with recursive timing events. The following just prints the next number on the countdown on a new line until limit is reached. A version on jsfiddle here.

function countdown(limit,initial,period){
    if (initial>=limit){
        document.getElementById('tag').innerHTML += '<br/>'+initial;
        window.setTimeout(function(){countdown(limit,--initial,period);},period);
    }
};

The above code does work, but the way I originally wrote it was with this line:

window.setTimeout(function(){countdown(limit,--initial,period);},period);

Kust like this:

window.setTimeout(countdown(limit,--initial,period),period);

Which doesn't work. Why must I wrap the function countdown() in function(){}? Is this the best way to do it? Why doesn't the way I tried originally work?

Thank you!

Was it helpful?

Solution

This is the best way to do this. window.setTimeout expects a function as its first argument.

window.setTimeout(function(){countdown(limit,--initial,period);},period);

is passing an anonymous function as the first parameter to setTimeout.

window.setTimeout(countdown(limit,--initial,period),period);

is passing the result of the executed function countdown as the first parameter to setTimeout. In your case, the result of countdown is always undefined.

For further illustration, you could have also passed in a function to window.setTimeout like this:

var myFunc = function(){countdown(limit,--initial,period);};
window.setTimeout(myFunc, period);

OTHER TIPS

First argument of setTimeout should be a function. When you write

window.setTimeout(countdown(limit,--initial,period),period);

you firstly call your function. It returns undefined. This is similar to call

window.setTimeout(undefined,period);

So yes, wrap your countdown into function(){} it the best way.

setTimeout accepts either function or code (to eval). Your countdown is a function, but

countdown(limit,--initial,period)

is function call result, which would be undefined, since it returns nothing. So, the second version could be simplified to

window.setTimeout(undefined, period)

which obviously wouldn't work.

While all other answers are good and explain why your second approach to invoking countdown(...) function doesn't work, I want to add that you aren't restricted to wrapping the countdown(...) into anonymous function. You can also use Function's bind method like so:

window.setTimeout(countdown.bind(null, limit,--initial,period),period);

Here the first parameter is the function's scope (as you don't reference this in countdown(...), you can safely set it to the null). Check out the documentation on the link provided if you have any questions.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top