Reputation: 1933
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 :-)
Upvotes: 0
Views: 79
Reputation: 113866
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.
Upvotes: 4
Reputation: 23778
Two problems.
this
is missing in your constructor function on scheduleItemService
.
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.
Upvotes: 0