I'm attempting to have a javascript object run a deferred method and when it's .done() call a function in that same object. I'm having issues because "this" becomes the deferred object instead of the object that called it.
PageObject.prototype.successFunction = function() {
console.log(arguments);
return console.log(this.name + " Success function called");
};
PageObject.prototype.loadPage = function(url) {
return $.when($.mobile.loadPage("pages/" + url))
.done(this.successFunction);
};
var pg = new PageObject();
pg.loadPage("test.html");
How do I send "this" into the successFunction? This PageObject is going to be extended by others as well, so knowing "this" when running successFunction will be very handy.
It seems simple, and probably has a simple answer. I was looking into .apply() but I'm not sure it helped. This post on stack overflow was helpful a little bit, but it broke the minute I put it into the .done() function.
Functions as parameters (with parameters) -- JavaScript
jQuery's proxy
will return a function bound to a specific context:
PageObject.prototype.loadPage = function(url) {
return $.when($.mobile.loadPage("pages/" + url))
.done($.proxy(this.successFunction, this));
};
There is also ES5's bind
which operates similarly but needs to be shimmed in older browsers
PageObject.prototype.loadPage = function(url) {
return $.when($.mobile.loadPage("pages/" + url))
.done(this.successFunction.bind(this));
};
apply
and call
can execute a function immediately with the specified context, but proxy
and bind
return a function that can be used later or passed to other functions.
The this
"variable" in JavaScript is called the "calling object" and is determined when its enclosing function is called (not when it's defined). It can be set a few different ways:
.
operator (e.g. myObject.myFunction()
)call()
or apply()
methodsbind()
methodThe important thing to understand is that (aside from method 3 above), it's all about how the function is called when it's called, not how it's referenced, not how it's stored, not where it's created.
In your case, you're passing this.successFunction
as a function reference to be called by jQuery, but it doesn't call it that way (because it just got a reference to the function, not any information on how that function should be called).
There are a few fancy tricks you can use with jQuery's $.proxy()
or ES5's .bind()
methods, but when it comes down to it, the most straightforward way to handle it is to simply retain this
through a closure-scoped variable and use a function wrapper:
PageObject.prototype.loadPage = function(url) {
var self = this;
return $.when($.mobile.loadPage("pages/" + url))
.done(function () { self.successFunction(); });
};
Note that we're using method 1 to explicitly bind successFunction
's calling object to be the same as loadPage's calling object. It's short, simple, clear, works fine under ES3, and doesn't depend on jQuery.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With