how do I setInterval to call a function within a class
Solution 1
The value of this
is set depending on how a function is called. When you call a function as a constructor using new
then this
will refer to the object being created. Similarly when you call a function with dot notation like run.start()
then this
will refer to run
. But by the time the code run by the setInterval
is called this
doesn't mean what you think. What you can do is save a reference to this
and then use that reference, like the following:
function Run(){
var self = this;
self.start = function(){
self.interval = setInterval(function() { self.draw(); },1000);
};
self.draw = function(){
//some code
};
}
var run = new Run();
run.start();
Note also that you've created a function called run
and a variable called run
- you need to give them different names. In my code (bearing in mind that JS is case sensitive) I've changed the function name to start with a capital "R" - which is the convention for functions intended to be run as constructors.
EDIT: OK, looking at the other answers I can see that just maybe I overcomplicated it and as long as draw()
doesn't need to access this
it would've been fine to just say:
this.interval = setInterval(this.draw, 1000);
But my point about not giving your constructor and later variable the same name still stands, and I'll leave all the self
stuff in because it is a technique that you will need if draw()
does need to access this
. You would also need to do it that way if you were to add parameters to the draw()
function.
Solution 2
The bind() method!
See the following example in ES6:
<!DOCTYPE html>
<html>
<body>
<canvas id="canvas" width="200" height="200" style="border: 1px solid black"></canvas>
<script>
class Circles {
constructor(canvas, r = 5, color = 'red') {
this.ctx = canvas.getContext('2d')
this.width = canvas.width
this.height = canvas.height
this.r = r
this.color = color
setInterval(
this.draw.bind(this),
1000
)
}
draw() {
this.ctx.fillStyle = this.color
this.ctx.beginPath()
this.ctx.arc(
Math.random() * this.width,
Math.random() * this.height,
this.r,
0,
2 * Math.PI
)
this.ctx.fill()
}
}
</script>
<script>
var canvas = document.querySelector('#canvas')
var circles = new Circles(canvas)
</script>
</body>
</html>
Comments
-
fenerlitk almost 2 years
I have a class like:
function run(){ this.interval; this.start = function(){ this.interval = setInterval('this.draw()',1000); }; this.draw = function(){ //some code };} var run = new run(); run.start();
however I can't seem to reference/call
this.draw()
within the setInterval, it saysthis.draw()
is not a function, and if I remove the quotes it says useless setInterval call, what am I doing wrong? -
mu is too short over 12 years
this.draw
won't work ifdraw
needs the rightthis
inside it, whendraw
is called in thesetInterval(this.draw, 1000)
version,this
will bewindow
insidedraw
. All theself
stuff is necessary ifdraw
uses an instance properties (i.e. if it really is a method rather than just a plain function). -
nnnnnn over 12 yearsTrue. When I added my "edit" I was just looking at
draw
containing "some code" which may not needthis
, but then it probably won't be a very useful method if it doesn't, so...I'll edit my edit... -
fenerlitk over 12 yearsThanks for your answer, removing the quotes and the () worked, then I noticed every time the interval run the variables inside the draw function ponting to this was undefined! then I set everything to self, everything is solved, but, I still don't understand why and how this works, do you mind explaining a bit more please? thanks again. :) oh okay, so this points to window inside the setInterval, HOW WEIRD! anyway is there a better way of doing this, self doesn't look right to me :\
-
nnnnnn over 12 yearsWell you don't have to call the variable "self", but semantically that's what it is. Some people say "me" or something instead. A lot of people say "that" instead, but I hate "that" because it is wrong semantically ("this" and "that" should not be the same thing). Whatever you name it though the concept is still the best way to do it (that I know of). For more info on how "this" works have a look at what MDN has to say about it (or just google "javascript this" and see what turns up).
-
fadedbee almost 6 years@NickSteele Could it be because it causes an extra function invocation before each of the interval's call to
draw()
? I agree that Yas's solution is more readable. -
raddevus about 2 yearsYes!! Thank you so much. So glad I found this answer. I was trying to call setInterval from JavaScript class constructor but none of my class variables were available. bind() solved it. 👍🏽