1

I am programming a little timer. The code is as follows:

var counter = {
    seconds: 100,
    clock: function () {
        $('input').val(this.seconds);
        this.seconds -= 1;
        setTimeout(this.clock(), 1000);
    }
};

counter.clock();

with a working example on http://jsfiddle.net/4ktEG/

Somehow each time I run the code I get a different answer. What is the problem?

1
  • 2
    This might give you more of what you are looking for: jsfiddle.net/4ktEG/13 Commented Jul 31, 2011 at 16:10

6 Answers 6

7

This does the countdown you're looking for.

var counter = {
    seconds: 100,
    clock: function () {
        $('input').val(this.seconds);
        this.seconds -= 1;
        setTimeout(function(){counter.clock()}, 1000);
    }
};

counter.clock();

http://jsfiddle.net/4ktEG/13/

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

1 Comment

No problem. I thought initially something else was going on, which was I posted it as a comment instead of an answer.
1

jQuery has the jQuery.proxy()[docs] method for binding the this value.

setTimeout($.proxy(counter,'clock'), 1000);

The $.proxy will return a function that invokes counter.clock with counter bound as the this value.


Or you can use it like this to permanently bind counter to counter.clock:

var counter = {
    seconds: 100
};

counter.clock = $.proxy( function () {
    $('input').val(this.seconds);
    this.seconds -= 1;
    setTimeout(this.clock, 1000);
}, counter);

counter.clock();

Example: http://jsfiddle.net/bmYAN/

Comments

0

If you want the input to show "100", then disappear when the setTimeout is called, then you have to take out the brackets on "this.clock()"

Therefor:

var counter = {
seconds: 100,
clock: function () {
    $('input').val(this.seconds);
    this.seconds -= 1;
    setTimeout(this.clock, 1000);
}
};

counter.clock();

1 Comment

That's not what I want. I want a counter that goes 100, 99, 98, etc.
0

When you say

setTimeout(this.clock(), 1000); //the clock method will be called right away.

Use this instead

setTimeout(this.clock, 1000); 

Comments

0

Use:

var counter = {
    seconds: 100,
    clock: function () {
        $('input').val(counter.seconds);
        counter.seconds -= 1;
        setTimeout(counter.clock, 1000);
    }
};

counter.clock();

You used "this" inside a function, what you want is to refer to the "counter" object.

2 Comments

I still doesn't do what I want. It shows 100, and then nothing.
and how is it different? explain please!
0

The timeout will execute in a global context. Hence the 'this' inside the handler will refer to the global context. You have to bind the function to the wanted context to achieve the desired result. Look into function.call or function.apply which take a context parameter.

var counter = {
    seconds: 100,
    clock: function () {
        $('input').val(this.seconds);
        this.seconds -= 1;
        var closure = function() {
            counter.clock.call(counter);
        };

        setTimeout(closure, 1000);
    }
};

counter.clock();

Comments

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.