Javascript function context, “apply” method and lost “this” object
How many times you had problem or were asked about what happened to this object in your function? Or why this is not an object you expect it to be? Probably these times you have to remind yourself or your fellow programmer about function context.
First of all I have to ask you all a pretty lame question. If you write function in JS block right inside your HTML, what this keyword will refer to?
<script type="text/javascript">
function testThis(){
//who is "this"
}
</script>
And now to the real example.
Let’s say you build a simple Javascript object:
<script type="text/javascript">
var mathObj = {
pi: 3.14,
getCircumference : function(data) {
alert(this.pi * 2 * data.radius);
}
}
mathObj.getCircumference(10);
</script>
You have properties, you have functions, you can use this keyword to access properties of the object from its functions. Everyone is happy.
Now we want to add function that will get some server data using AJAX and run one of the functions our object has.
(To all who wondered what is $ stands for – I use JQuery framework in all my JS samples)
<script type="text/javascript">
var mathObj = {
pi: 3.14,
getCircumference : function(data) {
alert(this.pi * 2 * data.radius);
},
getRemoteCircumference: function(url) {
$.getJSON(url, this.getCircumference);
}
}
mathObj.getRemoteCircumference("RadiusData.js");
</script>
If we have {“radius”:5} in RadiusData.js file you would expect the result of getCircumference would be 31.4 but you will get NaN. Why is that? Because this keyword in this case will refer to some kind of object with request data returned by JQuery. What can you do?
Solution number one is to use your object name:
...
getCircumference : function(data) {
alert(mathObj.pi * 2 * data.radius);
}
...
Ugly. You don’t have to return on object name in every function.
Solution number two is to use anonymous function and explicitly call your function:
....
getRemoteCircumference: function(url) {
$.getJSON(url, function(data){
mathObj.getCircumference(data);
});
}
...
Good enough solution, but again I don’t like reusing object name…
And now to my favorite solution.
<script type="text/javascript">
function getContextFunc(context, func) {
return function() {
func.apply(context, arguments);
};
}
var mathObj = {
pi: 3.14,
getCircumference: function(data) {
alert(this.pi * 2 * data.radius);
},
getRemoteCircumference: function(url) {
$.getJSON(url, getContextFunc(this, this.getCircumference));
}
}
mathObj.getRemoteCircumference("RadiusData.js");
</script>
Here apply function will come in handy. getContextFunc returns anonymous function that will run our original method in given context.
See some documentation
A few posts you might find interesting:

I might be missing something but couldn’t you just use:
$.getJSON(url, mathObj.getCircumference));
@Brandon
Sure you can, but you will not be able to use this in getCircumference cause it will run in the context of AJAX request object.
There is a difference between mathObj.getCircumference() (calling object method) and mathObj.getCircumference (passing function reference as callback) this is what probably get you confused
This solution can be cleaned up even further by putting getContextFunc into function thusly:
Function.prototype.inContext = function(context){
var func = this;
return function(){
return func.apply(context, arguments);
};
};
So that when you want to call it you can simply say:
getRemoteCircumference: function(url) {
$.getJSON(url, this.getCircumference.inContext(this));
}