0

I'm new to JS and especially to prototypes. I have this class and I cannot figure out how to access the properties.

var Lobby = function (preloader, serverConn) {
  // Hold a reference to EventBus
  this.serverConn = serverConn;
  this.preloader = preloader;

  this.scheduleItemService = new ScheduledItemService(this.preloader);
  this.stage = new createjs.Stage("lobbyCanvas");
};

Lobby.prototype.start = function(me, signedRequest) {
    sendMessage(data, function() {
       // inside this scope this.stage is undefined!
       renderLobbyImages(this.stage, this.scheduleItemService);
    });
};

function renderLobbyImages(stage, scheduleItemService) {
  stage.update();
};

Calling code:

var lobby = new Lobby(preloader, serverConn);
lobby.start(me, status.authResponse.signedRequest);

What am I doing wrong accessing 'renderLobbyImages' ??

Thank you :-)

Shvalb
  • 1,462
  • 1
  • 22
  • 48

2 Answers2

4

In javascript, this is not resolved based on where it is declared/used. It is resolved when it gets called. (see: How does the "this" keyword in Javascript act within an object literal?).

Therefore, in the code above, since this is called in the callback to sendMessage(), and since sendMessage is asynchronous (meaning the callback will be called long after the call to start() have returned), this is therefore referring to the global object (which is window in web browsers, something unnamed in node.js).

So effectively, your code is doing this (no pun intended):

sendMessage(data, function() {
   renderLobbyImages(stage, scheduleItemService);
});

Since there are no global variables called stage or scheduleItemService both are effectively undefined!

Fortunately, there is a workaround for this. You can capture the correct object in a closure:

var foo = this;
sendMessage(data, function() {
   renderLobbyImages(foo.stage, foo.scheduleItemService);
});

Alternatively, you can pass the correct object (this) into an IIFE:

(function(x){
    sendMessage(data, function() {
        renderLobbyImages(x.stage, x.scheduleItemService);
    });
})(this); // <-------- this is how we pass this

or:

sendMessage(data, (function(a){
    return function(){
        renderLobbyImages(a.stage, a.scheduleItemService);
    }
})(this));

Or in this case, since stage and scheduleItemService are not functions, you can even pass them directly:

sendMessage(data, (function(a,b){
    return function(){
        renderLobbyImages(a,b);
    }
})(this.stage, this.scheduleItemService));

There are lots of solutions to this problem. Just use the one you're most comfortable with.

Community
  • 1
  • 1
slebetman
  • 93,070
  • 18
  • 116
  • 145
0

Two problems.

  1. this is missing in your constructor function on scheduleItemService.

  2. Some functions you call to assign values seem to be not returning anything.

     new createjs.Stage("lobbyCanvas");
     new ScheduledItemService
    

Your calling method is alright.

this always refers to the calling object. When you say...

varlobby = new Lobby();
lobby.start();

... your calling object is lobby which has all the fields the start() function needs. But there initialization seems to be not working properly.

Please read this MDN starter guide.

Also we are having a some discussion about classical and prototype based OOP in this question. Please see the answer of Paul S for more about the tutorial I mentioned. Please see my answer if you need to see the tutorial in classical OOP light.

Community
  • 1
  • 1
Charlie
  • 18,636
  • 7
  • 49
  • 75
  • Your constructor function is ok. And you are calling it correctly. The only possibility is that `createjs.Stage` and `ScheduledItemService` don't create the properties as expected. So, they are 'undefined'. Please set a breakpoint there and see in the console if these functions work properly. – Charlie Dec 22 '15 at 17:55
  • I know what's the problem but I don't know how to solve it. if I call the method directly from the .start() method than everything is defined. *BUT* if I call the method within an inner function of the 'sendMessage' method - then it is undefined! – Shvalb Dec 22 '15 at 18:17