Reputation: 4783
function Push(apiInstance) {
this.api = apiInstance; // If I alert() here this is a valid object
this.pushNotification = window.plugins.pushNotification;
if ( device.platform == 'android' || device.platform == 'Android' )
{
this.pushNotification.register(
this.successHandler,
this.errorHandler, {
"senderID":"",
"ecb":"onNotificationGCM"
});
}
else
{
this.pushNotification.register(
this.tokenHandler,
this.errorHandler, {
"badge":"true",
"sound":"true",
"alert":"true",
"ecb":"onNotificationAPN"
});
}
}
Push.prototype.tokenHandler = function (token) {
this.api.registerDevice(token); // Suddenly this.api is undefined
};
var push = new Push(/* in my production code this is a valid object */);
I know that apiInstance
is valid as if I alert the instance in the constructor it shows as an object. For some reason when the tokenHandler callback is invoked this.api
is suddenly undefined.. any ideas why? OOP in JavaScript is so frustrating...
Upvotes: 1
Views: 67
Reputation: 872
That is because scoping in javascript is done on the functions level.
In this peace of code:
function Push(apiInstance) {
this.api = apiInstance; // If I alert() here this is a valid object
}
"this" - is the scope of the function Push. so, you can try to do next:
var api = {};
function Push(apiInstance) {
api = apiInstance; // If I alert() here this is a valid object
this.pushNotification = window.plugins.pushNotification;
if ( device.platform == 'android' || device.platform == 'Android' )
{
this.pushNotification.register(
this.successHandler,
this.errorHandler, {
"senderID":"",
"ecb":"onNotificationGCM"
});
}
else
{
this.pushNotification.register(
this.tokenHandler,
this.errorHandler, {
"badge":"true",
"sound":"true",
"alert":"true",
"ecb":"onNotificationAPN"
});
}
}
Push.prototype.tokenHandler = function (token) {
api.registerDevice(token); // Suddenly this.api is undefined
};
var push = new Push(/* in my production code this is a valid object */);
In this code api - will be variable not in scope of the function, but in "global scope" for the function Push.
Upvotes: 0
Reputation: 56726
The problem is that this:
this.tokenHandler
is just a function itself, and the function does not know anything about where it belongs to and what it's context should be. To work this around you can apply the following:
var self = this;
this.pushNotification.register(
function (token) {
self.tokenHandler(token);
},
This use of a closure will ensure that tokenHandler
is called with a self
context, which is an instance of a Push
Upvotes: 1
Reputation: 239663
When you do
this.pushNotification.register(
this.tokenHandler,
this.errorHandler, ...);
You are essentially passing the function object tokenHandler
and it doesn't know that it was bound to the current object. So when it is invoked by the register
function, as it is not bound to any object, JavaScript will pass the global object as this
(in Strict mode it will pass undefined
). To avoid that, you need to explicitly bind the current object with the function object, with Function.prototype.bind
like this
this.pushNotification.register(
this.tokenHandler.bind(this),
this.errorHandler.bind(this), ...);
Upvotes: 1