I've used a few tutorials on OOP in JavaScript. It seemed to go well, until I met the following...
Result of expression 'this.prepareFrame' [undefined] is not a function.
Ok. I'm using prototype and make use of the this keyword.
See my app.js page here...
// Plain "main" function called by the html page, like <script>main()</script>. This works nicely:
function main() {
engine = new AbstractEngine();
engine.init();
}
// Next creates a new instance of my AbstractEngine class. Seems to work so far:
function AbstractEngine() {}
// The init() method we called is defined afterwards:
AbstractEngine.prototype.init = function() {
this.initLoop();
}
// remark: I'm using "this", and according to the debugger, "this" refers to the AbstractEngine we made an instance of.
// Next, we define the initLoop method:
AbstractEngine.prototype.initLoop = function() {
setInterval(this.tick, 1000 / 30);
}
// Fine, everything works fine so far. Now get to define the "tick" method:
AbstractEngine.prototype.tick = function() {
this.prepareFrame();
this.update();
}
// Ok, we're in trouble. The error message is output to the console and I don't understand why... The prepareFrame() and update() methods are defined right afterwards:
AbstractEngine.prototype.update = function() {
console.log('updating!');
}
AbstractEngine.prototype.prepareFrame = function() {
console.log('preparing frame');
}
// I read my code twice, but didn't find beginner's mistakes like typo or whatever. But well, cosnider I'm a beginner
This:
Should be:
or alternately:
Explanation: when you pass simply
this.tick, that is the same as doing the following:But now, when
tempis called, JavaScript doesn't know what thethispointer should be; that information gets lost, and it ends up getting bound to the global object (window), or tonullif you are in strict mode.So you need to somehow ensure that
this.tickis called as a method with the appropriatethispointer. There are two ways to do this:var that = this, you can properly callthat.tickas a method on the originalthispointer.bind()ing thethis.tickfunction tothis, you ensure it is called as a method with the appropriatethisevery time: in other words, you could even dovar temp = this.tick.bind(this)andsetInterval(temp, 1000 / 30).Note that
bindis not available in older browsers (notably IE <= 8 and all Safaris so far up to and including 5.1), in which case you'd need something like es5-shim.