Bachalo
Bachalo

Reputation: 7219

Scope issue in Javascript with setTimeout

Scope issue, I thought function statements were always hoisted to the top of the current context. So why is 'hideNav()' undefined in the following?

var t;


function showNav(bflag){
clearTimeout(t);
if(bflag===true){
    $("#tS2").stop(false,false).animate({
                'bottom':'0'
            }, 1000);
}else{

    t=setTimeout("hideNav()",1000);

}
}

function hideNav(){
$("#tS2").stop(true,false).animate({
                'bottom':'-125px'
            }, 1000);
}

Upvotes: 1

Views: 113

Answers (2)

jfriend00
jfriend00

Reputation: 707258

Don't use a string with setTimeout() in this case.

Change it to:

t = setTimeout(hideNav, 1000);

Using a string with setTimeout() forces it to use eval() to evaluate your string and when it does that, it uses the global context, not your local context. So, my guess is that hideNav() isn't actually a global function (you probably have this code wrapped inside some other function).

Besides, it's ALWAYS better to use a direct function reference rather than a string and a lot faster too. Just remember when you use the direct function reference, do NOT put the parentheses afterwards. You want a reference to the function, you don't want to immediately execute it and pass the return value which is what it would do if you used t = setTimeout(hideNav(), 1000);

Upvotes: 2

Anurag
Anurag

Reputation: 141869

Change,

setTimeout("hideNav()",1000);

to

setTimeout(hideNav, 1000);

hideNav is only defined in the current context, but you are passing a string to setTimeout. That string will be eval'd when the timeout occurs in the context of the global object. Since your hideNav function is not defined in the global object, it will throw an exception.

By directly passing a reference to the function to setTimeout, you don't have to worry about it.

Upvotes: 6

Related Questions