Geeks With Blogs
AzamSharp Some day I will know everything. I hope that day never comes.

While implementing a solution which involved Ajax calls I faced some difficulty when assigning the coordinates to the DIV object. The reason was that the variable was defined locally in the function and was not accessible by the function that was called in a separate scope. Let's see this in action.

The button below fires the changeText method and passes the event.

<input type="button"  value="press me" onclick="changeText(event)" />

function changeText(e)
{
    var ev = e || window.event;
    var div = document.getElementById("display");
    this.clientX = ev.clientX;
   
    div.innerHTML = 'this is the default text' + ev.clientX;
   
    window.setTimeout(function() { div.innerHTML = 'text is changed!' + ev.clientX; },1000);
   
}

The window.setTimeout function will be fired after every 1 second. The ev.clientX variables is NOT accessible from inside the anonymous function called after every 1 second. This is because the context in which the 'ev' variable is declared is different from the context in which the anonymous function will get executed. A fix for this problem is to declare the variable globally.

function changeText(e)
{       
    var ev = e || window.event;
    var div = document.getElementById("display");   
   
    x = ev.clientX;
    y = ev.clientY;
      
    div.innerHTML = 'this is the default text' + ev.clientX;
   
    window.setTimeout(function() { alert(x); div.innerHTML = 'text is changed!' + x; },1000);
   
}

In the above code the x and y are the global variables. This means they are part of the window object. You can also access them using the following code:

window.x and window.y && this.x and this.y

I would use window.x since this.x would be confusing since you can be in a different context.

You might be thinking that why not make the entire event object global like this:

ev = e || window.event (see no var keyword which makes the object global)

This will not work since the event is based function to function and in the anonymous function the ev will be resetted hence producing the ev.clientX = 0.

Let see how this works when using the custom objects. In this example we won't be using the global variables since they are expensive to create and we are also looking for a solution that does not invole using global variables.

function SimpleObject()
{
   
}

SimpleObject.prototype.changeT = function(e)
{
    var ev = e || window.event;
    var div = document.getElementById("display");
   
    this.x = ev.clientX;
           
    div.innerHTML = 'this is the default text' + ev.clientX;   
    window.setTimeout(function() { alert(this.x); div.innerHTML = 'text is changed!' + this.x; },1000);   
   
}

function changeText(e)
{  
    var simpleObject = new SimpleObject();
    simpleObject.changeT(e);

}

The line this.x = ev.clientX creates a new property 'x' on the SimpleObject. The property 'x' won't be recognized by the window.setTimeout callback function. This is because the setTimeout anonymous function is called in a different context. In the code below this.x is 'undefined'.

window.setTimeout(function() { alert(this.x); div.innerHTML = 'text is changed!' + this.x; },1000);   

If you are using MS AJAX library then there is an easy way to fix it.

window.setTimeout(Function.createDelegate(this,function() { alert(this.x); }),1000);

The call to Function.createDelegate will force the anonymous function to run under the context of the SimpleObject. And hence the 'this' keyword will refer to the CustomObject. But what if you are NOT using MS AJAX there is a little fix for that too.

 window.setTimeout(createRef(this,function() { alert(this.x); }),1000);

The createRef function assigns the anonymous method to the correct instance.

function createRef(instance,method)
{
    return function() {  method.apply(instance,arguments); };
}

Posted on Tuesday, March 4, 2008 10:47 AM | Back to top


Comments on this post: Closures, Context and this Keyword in JavaScript

# re: Closures, Context and this Keyword in JavaScript
Requesting Gravatar...
Thank you very much! I was going mad with this problem, but it was my fault not understanding the context of the this keyword!

Thumbs up for you!

Alessandro
Left by ripe on Mar 18, 2008 10:17 PM

Your comment:
 (will show your gravatar)


Copyright © Mohammad Azam | Powered by: GeeksWithBlogs.net