-1

I see the link about the use of this is jQuery. Yes, the problem was exactly this, but this situation is a completely different one, so please remove useless links to other questions and mark as duplicated because this can lead to confusion to a poor SO user looking for a more simple situation.

Also: my code is fully pasted here, not just a snippet, and my code is not using some complicated binding at all, is more basilar. So it's a complete new question for me

This is my full working code

var game = {
    status : {
        NOT_INITIALIZED : "gamepad:not_initialized",
        INITIALIZED     : "gamepad:initialized",
    },
    _selector : null,
    _status   : null,
    init : function( gamepad_selector ) {
        this._selector = gamepad_selector;
        $(this._selector).on(this.status.NOT_INITIALIZED, this.onNotInitialized);
        this.setState(this.status.NOT_INITIALIZED); // just to force the first console log
        $(this._selector).on(this.status.INITIALIZED, this.onInitialized);
        this.setState(this.status.INITIALIZED);
    },
    setState : function ( new_status ) {
        this._status = new_status;
        $(this._selector).trigger(new_status);
    },
    onNotInitialized: function () {
        console.log("onNotInitialized()");
    },
    onInitialized: function () {
        console.log("onInitialized()");
    },
}

The entry point is a call to game.init().

Note that on the init function, I can call setState using one of the predefined status. This works.

this.setState(this.status.NOT_INITIALIZED);

I tried to avoid using of this.setState, so I deleted this function and tried to set this._state directly into the event listeners.

This the significative parts of not working code:

init : function( gamepad_selector ) {
    ....
    console.log ("a");
    $(this._selector).on(this.status.NOT_INITIALIZED, this.onNotInitialized);
    console.log ("b");
    $(this._selector).trigger(this.status.NOT_INITIALIZED)
    console.log ("c");
    ....
},

onNotInitialized: function () {
    // I can't do this: throws an error
    this._status = this.status.NOT_INITIALIZED;
    console.log("onNotInitialized()");
},    

The problem: at runtime I got this error:

Cannot read property 'NOT_INITIALIZED' of undefined

related to

this._status = this.status.NOT_INITIALIZED;

The error is at runtime, not at 'compile' time (please forgive me the term), because I can see on the console log both a and b. But not c.

Why can I explicitly use this.status.NOT_INITIALIZED in init but not in onNotInitialized ?

realtebo
  • 23,922
  • 37
  • 112
  • 189

1 Answers1

2

The problem is to do with the way JavaScript binds the this variable - the full rules are quite complex, but the reason your code fails is that when you invoke the onNotInitialized method via the jQuery on() method this is not bound to your game object but to the element that triggered the event.

You can fix the issue by using the bind() function as follows:

$(this._selector).on(this.status.NOT_INITIALIZED, this.onNotInitialized.bind(this));
codebox
  • 19,927
  • 9
  • 63
  • 81
  • This is a solution, but not a good idea, I think. I prefer modify the code to access to `game.status. ....` and AVOID to modifiy the `this` pointer – realtebo Aug 13 '15 at 08:43