37

This is my first real dive into JavaScript. Sure I've used it before, but I've never really written anything from scratch.

Anyway, I'm having a very strange problem that I hope someone can figure out for me.

I'm trying to make the text from a div fade from black to white. Simple, yeah?

The following code works. It will change the color to white, however, the setTimeout time of 500ms is being ignored.

If you use Chrome and look at the JS console, you'll easily see that the doFade() method is being called almost instantaneously, not every 500 milliseconds.

Can anyone explain this?

var started = false;
var newColor;
var div;
var hex = 0;

function fadestart(){
    if (typeof fadestart.storedColor == 'undefined') {
        div = document.getElementById('test');
        fadestart.storedColor = div.style.color;
    }
    if(!started){
        console.log('fadestart');
        newColor = fadestart.storedColor;
        started = true;
        setTimeout(doFade(), 500);
    }
}

function fadestop(){
    console.log('fadestop');
    div.style.color = fadestart.storedColor;
    started = false;
    hex = 0;
}

function doFade(){
    if(hex<=238){
        console.log(hex);
        hex+=17;
        div.style.color="rgb("+hex+","+hex+","+hex+")";
        setTimeout(doFade(), 500);
    }
}
0

3 Answers 3

66

You need to get rid of the parentheses on doFade().

The parentheses invoke the function instantly.

Just use this instead: doFade

Sign up to request clarification or add additional context in comments.

15 Comments

pretty sure you don't need quotes. You should be able to put either doFade or "doFade". I think there might even be slight performance benefits to not converting the string "doFade" to the function handle.
@Surreal Actually, you want to pass the function without parentheses. Quoting it executes the passed code snippet in the global context, which can have vastly different results.
@Surreal Dreams setTimeout accepts function or a string to be eval'd as the callback. Functions in Javascript are first class objects and can be (often are) passed around freely around as such. As Javascript is incredibly dynamic, eval can (and should) almost always be avoided.
@akellehe, @deceze & @Angio: Thanks for correcting me. I felt reasonably confident about my answer, but I knew if I was wrong you guys would be all over me and I'd learn it right. :) So thanks.
Why do they have it execute immediately with parens? Is it so that you can have another function return the function to use as the timeout dynamically?
|
24
setTimeout(doFade(), 500);

This line says "execute doFade(), then pass whatever value it returns to setTimeout, which will execute this return value after 500 milliseconds." I.e., you're calling doFade() right there on the spot.

Skip the parentheses to pass the function to setTimeout:

setTimeout(doFade, 500);

Comments

4

I think you should use setTimeout(doFade, 500); or setTimeout("doFade()", 500);

4 Comments

The quoted call also works but is awful. See akellehe's answer for details.
Yes of course. My habit is passing a function or even an inline function. But quoting it is always another choice (of course not a better choice in most cases).
Nice one, the quoted function seems to be the only choice if passing a parameter.
Just noticed this one has a better answer: stackoverflow.com/questions/3800512/…

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.