0

I am working on a countdown timer written in Javascript. Fairly basic really. Just uses setInterval for the timing aspect. I wrote it using the prototype method of storing functions and variables so I can create a "class".

I call the code in this fashion.

function testTimer() {
    var newTimer = new CDTimer($("#voteTimer"),30,"");
    newTimer.start();
}

When the below code runs, console.log is printing out undefined or NaN.

function CDTimer (target, duration, callback) {
    this.target = target;
    this.duration = duration;
    this.callback = callback;
}

CDTimer.prototype.start = function() {
    this.start = new Date().getTime();
    this.interval = setInterval(this.update, 1000);
}

CDTimer.prototype.update = function() {
    console.log(this.duration, this.start);
    this.elapsed = this.duration - (new Date().getTime() - this.start) / 1000

    if (this.elapsed < 0) {
            clearInterval(this.interval);
            this.callback();
    }
    else {
        console.log(this.elapsed);
        $(this.target).text(this.elapsed);
    }
}

CDTimer.prototype.stop = function() {
    clearInterval(this.interval);
}

I must be missing something silly. What is happening to my variables and their values?

Thanks for the insight.

1
  • 1
    What do you expect this to refer to? You havent created any objects using your constructors. Commented Sep 19, 2012 at 9:27

1 Answer 1

4

The function called from setInterval is provided a this which is the window, not the timer.

You may do this :

CDTimer.prototype.start = function() {
    this.start = new Date().getTime();
    var _this = this;
    this.interval = setInterval(function(){_this.update()}, 1000);
}

Note that the MDN offers a detailed explanation.

EDIT following comment : if you don't want to create a new variable in the start function, you could do this :

CDTimer.prototype.start = function() {
    this.start = new Date().getTime();
    this.interval = setInterval(function(_this){_this.update()}, 1000, this);
}

But I'm not sure the readibility is improved by this move of the variable creation and it's not compatible with IE (if you don't patch it, see MDN's solution).

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

5 Comments

This was exactly the answer. I see the issue now that you have pointed it out. The this was not referring to CDTimer since it was in the function() scope for setInterval. Correct? Also, thanks for linking me to the MDN, I had no idea it existed.
I wonder, can you skip making a variable by passing a reference to oneself into function(). Something like function(this) { ... }?
A solution for new browsers would be to make a bound function. But I don't recommend it and it's not really lighter.
"The bind function is a recent addition to ECMA-262, 5th edition; as such it may not be present in all browsers." That right there is a deal breaker for most. :/
Thanks for your edit. It offers another good solution but I agree that the first solution seems to be more readable.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.