I think I’m missing some key concept regarding objects and prototype functions in JavaScript.
I have the following:
function Bouncer(ctx, numBalls) {
this.ctx = ctx;
this.numBalls = numBalls;
this.balls = undefined;
}
Bouncer.prototype.init = function() {
var randBalls = [];
for(var i = 0; i < this.numBalls; i++) {
var x = Math.floor(Math.random()*400+1);
var y = Math.floor(Math.random()*400+1);
var r = Math.floor(Math.random()*10+5);
randBalls.push(new Ball(x, y, 15, "#FF0000"));
}
this.balls = randBalls;
this.step();
}
Bouncer.prototype.render = function() {
this.ctx.clearRect(0, 0, 400, 400);
for(var i = 0; i < this.balls.length; i++) {
this.balls[i].render(this.ctx);
}
}
Bouncer.prototype.step = function() {
for(var i = 0; i < this.balls.length; i++) {
this.balls[i].yPos -= 1;
}
this.render();
setTimeout(this.step, 1000);
}
I then create an instance of Bouncer and call its init function like so:
$(function() {
var ctx = $('#canvas')[0].getContext('2d');
var width = $('#canvas').width();
var height = $('#canvas').height();
var bouncer = new Bouncer(ctx, 30);
bouncer.init();
});
The init() function will call step which has a setTimeout to loop the step function.
This works on the first call to step(). However, on the second call (when setTimeout fires step) the instance variable “balls” is undefined. So, in my step function, the second call will blow up saying there is no “length” property for undefined.
Why do I lose my instance information when calling step from setTimeout()?
How could I restructure this so I can loop via a timeout and still have access to those instance variables?
When you call
setTimeout(this.step, 1000);, thestepmethod loses its desired context ofthis, as you’re passing a reference to thestepmethod. In the way that you’re doing it now, whenthis.stepgets called throughsetTimeout,this === windowrather than yourBouncerinstance.This is easy to fix; just use an anonymous function, and keep a reference to
this: