Will Ashley Will Ashley - 3 months ago 11
Javascript Question

Javascript binding issue not resolved by calling bind

I am trying to recursively call a function until the game has ended, however, during the execution "this" gets reset to 'window', which causes the following error: "cannot read property 'step' of undefined."

I have tried rewriting the offending line as

this.game.bind(this).step();


as well as

this.game.step.bind(this);


Neither are working. For context, step is just a function that calls two helpers in Game that move objects and look for collisions, when I used those instead of step, the error remained.

/* globals key */
const Game = require('./game.js');
let speed = 1;


function GameView(ctx) {
this.ctx = ctx;
this.game = new Game();
}

GameView.prototype.start = function (callback) {
// let that = this
this.bindKeyHandlers();
this.animate(0);
};

GameView.prototype.animate = function(time) {

speed += 1;
if (speed >= 605) {
speed = 0;
};

this.game.step();
this.game.draw(this.ctx, speed);
if(!this.game.lose()){
requestAnimationFrame(this.animate());
}
else {
this.ctx.fillStyle = "white";
this.ctx.font = "italic "+24+"pt Arial ";
this.ctx.fillText(`Game Over \n Press Enter to restart`, 100,200 );
key('enter', ()=>{
this.game = new Game();
this.start();
});
}
};


GameView.prototype.bindKeyHandlers = function() {
key('d', () => {
this.game.ship.power([2, 0]);
});
key('a', () => {
this.game.ship.power([-2, 0]);
});
key('s', () => {
this.game.ship.power([0, 2]);
});
key('w', () => {
this.game.ship.power([0, -2]);
});
key('l', () => {
this.game.ship.fireBullet();
});
};


module.exports = GameView;

Answer

Your problem is that this of the animate function does not refer to the context you wish it to. So your offending line (or lack thereof) is completely elsewhere.

Function.bind returns a function and you need to this new bound functions somewhere and the perfect place for this is the constructor. Here's an example:

function GameView(ctx) {
  this.ctx = ctx;
  this.game = new Game();
  this.animate = this.animate.bind(this)
}

See this jsfiddle for more, remember to open your developer console to witness the error from calling notBound

Hope this helps!

Comments