Erik
Erik

Reputation: 559

JavaScript addEventListener add a reference to the current object

I have simplified my code to illustrate the problem.

function SnakeGame ()
{
    this.snakeDirection         = 'right';

    this.Init = function ()
    {
        window.addEventListener('keydown', this.keyboardInput, false);
    }

    this.keyboardInput = function (event, SnakeGameObject)
    {
        console.log(SnakeGameObject); //Error since I can't pass this variable...
        console.log(event.keyCode); //Works
    }
}

Within the this.keyboardInput function I try to change the variable this.snakeDirection; problem is that I can't get a reference to the SnakeGame object. Within the keyboardInput function this refers to window. I understand why it refers to window, but I can't think of a solution...

The full code can be seen here: http://eriknijland.nl/stackoverflow/snake_event_listener/

Upvotes: 0

Views: 2762

Answers (3)

Alnitak
Alnitak

Reputation: 339816

If targeting ES5 (and you should be), you should write:

window.addEventListener('keydown', this.keyboardInput.bind(this), false);

which will ensure that the callback is always called with this as its context.

Upvotes: 1

Elias Van Ootegem
Elias Van Ootegem

Reputation: 76405

Though Mythril's answer is correct, I'd suggest you not to use methods as event callbacks. Because: a) they're public, so can be overruled quite easily once your code gets bigger and b) they're publicly accessible:

var snakeInstance = new SnakeGame();
var otherObject = new SomethingElse();
snakeInstance.keyboardInput.apply(otherObject,[]);//invokes method, uses self, though self !== otherObject, but snakeInstance.

So I'd use a closure:

function SnakeGame()
{
    this.snakeDirection = 'right';
    var keyBoardInput = (function(that)
    {
        return function(e)
        {
            console.log(that);
            console.log(e.keyCode);
        }
    })(this);
    this.Init = function()
    {
        document.body.addEventListener('keydown',keyboardInput,false);
    }
}

Also bear in mind that your code isn't exactly X-browser compatible (addEventListener && attachEvent?)

Upvotes: 2

Lucas Green
Lucas Green

Reputation: 3959

Try this:

function SnakeGame ()
{
    var self = this;
    this.snakeDirection         = 'right';

    this.Init = function ()
    {
        window.addEventListener('keydown', this.keyboardInput, false);
    }

    this.keyboardInput = function (event)
    {
        console.log(self); 
        console.log(event.keyCode); //Works
    }
}

Upvotes: 0

Related Questions