This is a subject that comes up frequently on StackOverflow. Some questions approach it from seeing it in code but not understanding why, while others approach it from the opposite side — needing it but not knowing that they need it to solve their problem.
-
What is
this?thisis a context-sensitive variable. It is used to refer to the current context/object. It’s value or meaning depends on where and when it is used. Let’s look at a few, quick, examples.-
On an element
<input type="checkbox" id="chk_123" name="chk[]" value="123" onclick="alert(this.value;)" />Demo:
<—- click me.In this case,
thisis the input element containing the code -
In general functions
function sayWindowName() { alert(this.name); }The above function will alert the value of
window.name. General functions, like the one above, operate in the window context andthisrefers to thewindowobject. -
In constructor functions
function Widget(name) { this.name = name; this.sayName = function() { alert(this.name); } } var bob = new Widget("Bob"); alert(bob.name); //case 1 bob.sayName(); //case 2 setTimeout(bob.sayName,0); //case 3In the above, case 1 will open an alert dialog with “Bob”; case 2 will also open an alert dialog with “Bob”; case 3 will, however, open an alert dialog with nothing. For the first two cases,
thisis referring to the Widget objectbobbut not in the third case. We can make a small change and see what’s happening, though.window.name = "John"; setTimeout(bob.sayName,0); //case 4Now, in the fourth case, we get an alert dialog with “John”.
setTimeoutis using the function frombobbut in the window context. The same is also true for event listeners which is how the issue most often comes up.
-
-
Solving the problem for objects
What we need is a way for methods to refer to their associated object without relying on a special variable like
thiswhose value may change depending on how it is called.var self;to the rescue.Basically, we take advantage of variable scope to effectively cache the value of
this. Let’s look again at the Widget above with the change.function Widget(name) { this.name = name; var self = this; this.sayName = function() { alert(self.name); //note that here we use self instead of this. } } var bob = new Widget("Bob"); alert(bob.name); //case 1 bob.sayName(); //case 2 setTimeout(bob.sayName,0); //case 3Now all three cases display the same behaviour, which is what we usually want. This is a very simple example but demonstrates the importance of understanding and taking advantage of variable scope.
Also see previous, related, posts Prototype’s Bind and Curry and JavaScript Closures. I also recommend reading Richard Crockford’s article Javascript Closures as it is an extremely detailed look at that subject, and the execution context/scope issue specifically, in more detail than I have.
