The Tricky.net

The this keyword
If you go a bit further with javascript, you would certainly meet the famous keyword this, and certainly notice that it is the source of many of your problems if you play with classes and events.
Let's see an example:

 
var Family = function(){
 this.nbPersons = 0;
 window.onclick = this.addMember;                
}
 
Family.prototype.addMember = function(){
 this.nbPersons++;    
 document.body.innerHTML += 'New family member added! nbPerson is ' + this.nbPersons + '!<br/>';
}
 
var myFamily = new Family();
 

So we built a super basic class, called Family, which is also the constructor: the class function addMember is then registered as click event listener to the window object. The addMember function just increment the number of person in the family.
The class is then instanciated with the new keyword.

Mhmmm... if you try this and make some clicks on the window, you will notice that the addMember function is executed, but the nbPersons variable value is "NaN":
 
"New family member added! nbPerson is NaN"
 

And if you alert the variable nbPersons of myFamily:
 
alert(myFamily.nbPerons);
 

you get "0", not "NaN". Why this?

Apparently it's not the same variable. Actually, the keyword this does not represent the family object in the addMember function when called through an event listener, it is the window object.

Javascript uses the concept of context : when you call a function, the this object is the object through which you call your function.
What do we have here:
 
window.onclick = this.addMember;
 

At execution time, when an onclick occurs, the context object this is the window object.
Now you begin to understand: we are incrementing the variable nbPersons of the window object, which was not set. That's why we get "NaN"! And myFamily.nbPersons remains of course untouched, its value is always "0".

Ok, you got it (hopefully!). Now, we'll do what we wanted correctly, forcing the onclick event to call the function through what we want. We can use the apply function: it allows you to call a function, with an object as context (remember, the object represented by this in the function): exactly what we want! we use it like that:
 
theFunction.apply(contextObject);
 

All the functions have natively the apply function as property. Ok, but what do we use as context object? We have to find a variable representing the object. Here we go:
 
var that = this;
window.onclick = function(){Family.prototype.addMember.apply(that)};  // the first right manner
 

Explanation: that, when initialised, is the Family object. We assign then the addMember function to the onclick event. Warning here: we assign a function to call to the event. If we would have written
 
window.onclick = Family.prototype.addMember.apply(that);  // won't work!
 

then we would have assigned to onclick the result of the function! (here the value undefined, as the addMember function does not return anything)
Yep, it works now. But you can still take a pleasant shortcut:
 
var that = this;
window.onclick = function(){that.addMember()};  // the right manner, shortcuted
 

The final way, fully functionnal! So remember: if you get a message like
 
"this.yourFunction is not a function"
 

And it seems to you that what you wrote for your event listener is right, you probably have a problem with this!

Hope this small article will help you to understand better what is this "this" object, often a bit abstract for semi-beginners, and how contexts can influence the call to your class functions.

Questions? check the new forum!
Comments
Search RSS
Only registered users can write comments!

3.23 Copyright (C) 2007 Alain Georgette / Copyright (C) 2006 Frantisek Hliva. All rights reserved."