Scott Klarr Jr
Javascript: passing object self reference to anonymous functions nested within multiple objects
I know the title of this post is a little complicated but I feel it best describes the problem at hand. In Javascript, objects, arrays and variables are all technically the same thing which allows you to do some interesting stuff - such as nesting functions inside arrays inside variables inside objects inside variables. There are of course issues of scope when doing this sort of thing, though. One problem I recently came across was that I needed to reference the parent object's self from within an anonymous function that is nested within an array.
Here is some code one might initially write before realizing it will not work as intended:
SomeClassName = function() {
this.ajaxError = function(textStatus) {
// Do error routine
}
this.functionName = function(){
$.ajax({
url: "ajax.php",
type: "GET",
cache: false,
dataType: "html",
success: function(msg,textStatus) {
if(textStatus == "success") {
// Success routine
} else {
this.ajaxError(textStatus);
}
},
error: function(XMLHttpRequest, textStatus, errorThrown) {
this.ajaxError(textStatus);
}
});
}
}
The problem is the two instances of this.ajaxError(textStatus); within the anonymous functions. When you use a self reference inside an anonymous function, it will reference the immediate parent object in which the anonymous function was declared. In this case, this would reference to the array of settings being passed to the jQuery function. For example, if within the Success routine block of code I referenced this.url, it would return the string "ajax.php" because self is pointing to the array object.
The solution is actually quite simple but perhaps not very obvious at first (thus the reason I am bothering to write this article). Nested objects allow you to reference variables declared in any parent object (so long as they are not re-declared within the current object block). So what you do is declare a variable that points to the desired object's self. To do this, I added var objectPointer = this; immediately before the nested object code. We can then reference objectPointer from within nested objects and their anonymous functions. Here is the corrected version of the above code.
SomeClassName = function() {
this.ajaxError = function(textStatus) {
// Do error routine
}
this.functionName = function(){
var objectPointer = this;
$.ajax({
url: "ajax.php",
type: "GET",
cache: false,
dataType: "html",
success: function(msg,textStatus) {
if(textStatus == "success") {
// Success routine
} else {
objectPointer.ajaxError(textStatus);
}
},
error: function(XMLHttpRequest, textStatus, errorThrown) {
objectPointer.ajaxError(textStatus);
}
});
}
}



bibby Jun 01, 2009
An alternative solution, and one that I frequently use, is to reference the object I want to call in the hash that I'm passing. This is generally limited to $.ajax in particular, but I'll explain.
As you pointed out, "this" in any of the $.ajax callback methods references the object of parameters ( like this.url ), so you can add your object to that without doing the "var that=this" routine.
$.ajax({url:'some.php', objectPointer:this, ..});
You can now use this.objectPointer in your callbacks, limiting access to your original object to just the callbacks.
Because assigning objects creates references, an even better solution would have been to assign an ajaxError to the object of parameters referencing your original object's:
$.ajax({url:'some.php', ajaxError:this.ajaxError, .. });
Then, your first code would have worked as you expected.
~!b
Martin Pape Aug 15, 2009
Thanks, you saved my day with the objectPointer in the anonymous function.
Abercrombie And Fitch Feb 19, 2010
Thank you very much for your geat post,Learned a lot and saw a lot about a lot!
Yeni Diziler Mar 02, 2010
Thank you very much for your geat post...