Reputation: 116423
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?
Upvotes: 1
Views: 96
Reputation: 322612
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/
Upvotes: 1
Reputation: 3176
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();
Upvotes: 0
Reputation: 5659
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.
Upvotes: 0
Reputation: 69915
When you say
setTimeout(this.clock(), 1000); //the clock method will be called right away.
Use this instead
setTimeout(this.clock, 1000);
Upvotes: 0
Reputation: 3965
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();
Upvotes: 0
Reputation: 49238
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();
Upvotes: 7