JavaScript has a reserved keyword called this
that references something different depending on where you are in a JavaScript program.
In this post I’m going to summarize, by example, some different contexts and discuss what “this” would represent in each case. Note that all of these examples assume you’re developing client-side JavaScript in a browser.
In the Global Context
What happens if you reference this
in the global context (i.e., not inside any function)?
console.log(this === window); // true
You can test this on any page in your dev tools by typing that line into the console.
As that code demonstrates, this
in the global context refers to the window
object. Look at the following code and the subsequent outputs:
this.message = "Check this out.";
window.message = "Check this out.";
console.log(this.message); // "Check this out."
console.log(window.message); // "Check this out."
console.log(message); // "Check this out."
You can view this code in action using this JS Bin.
So what’s going on here? The first two lines are doing the exact same thing — creating a global variable called “message” and setting its value to “Check this out.” This fact is demonstrated by the three console messages that follow, all showing the same result.
In Function Context
So what happens when you refer to this
in the context of a function, or closure?
In a simple example with no futher nesting of functions, it will depend on whether you’re using strict mode:
function checkThisOut () {
console.log(this === window); // true
console.log(this); // object global
}
checkThisOut();
As you can see, nothing’s changed from the global context (i.e. this
still references the window object). Now let’s try in strict mode:
function checkThisOut () {
"use strict";
console.log(this === window); // false
console.log(this); // undefined
}
checkThisOut();
If I understand correctly, as Nicholas Zakas points out, the behaviour shown in the “use strict” example is in order to prevent accidental globals. There could be more to it that I’m not fully understanding, but it seems that’s the main reason for the difference here.
In a Module Pattern
Recently I discussed the module pattern I’m currently using when writing JavaScript.
Let’s look at what this
references in the context of such a pattern:
var s,
PrimaryNameSpace = {
settings : {
first: true,
second: false,
foo: 'bar'
},
init: function () {
console.log(this); // references PrimaryNameSpace
},
nextMethod: function () {
},
anotherMethod: function () {
}
};
PrimaryNameSpace.init();
In the module pattern context, inside any of the individual methods (that is, the functions), this
will reference the entire module. In fact, if you view the console message created inside the init()
method in your developer tools, you’ll see something like the following:
The console shows you an object (the namespace, or module), then you can drill down into the object to view the different methods, as well as all the values defined in the settings
object.
Thus, inside the init()
method, you can reference the modules and settings using this
in the following manner:
/* ... other code here ...*/
init: function () {
s = this.settings;
this.nextMethod();
this.anotherMethod();
console.log(s);
},
/* ... other code here ...*/
PrimaryNameSpace.init();
Using this
to reference the other methods and the settings prevents us from having to write the references in long form. The following would be equivalent to what is written above:
/* ... other code here ...*/
init: function () {
s = PrimaryNameSpace.settings;
PrimaryNameSpace.nextMethod();
PrimaryNameSpace.anotherMethod();
console.log(s);
},
/* ... other code here ...*/
And in both cases, the console message would show:
What About a Nested Function?
If however, you have an anonymous function inside one of the methods, then the value of this
changes, and the module object is no longer accessible via this
. So the long form syntax would be necessary, as shown here:
/* ... other code here ...*/
init: function () {
s = this.settings;
(function () {
this.nextMethod();
// [object Window] has no method 'nextMethod'
})();
},
/* ... other code here ...*/
The comment I’ve inserted in the code above displays the message from the console, which demonstrates that inside the anonymous function, this
is a reference to the global “window” object, rather than being a reference to the PrimaryNameSpace
object.
And, as we saw earlier, using strict mode would make this
undefined, rather than a reference to the global object.
Summing Up
If nothing else, this post should demonstrate that using this
can be a useful shortcut. But all the while, keep in mind how the context can change the value of this
as well how it behaves in strict mode.
I’ve only scratched the surface of this topic, so here are some further posts discussing the this
keyword:
And if you have any corrections to what I’ve said, please add them to the comments and I’ll update accordingly.
Related posts:
- My Current JavaScript Design Pattern
- Why Use the Triple-Equals Operator in JavaScript?
- Some Random JavaScript Coding Tidbits
via Impressive Webs http://www.impressivewebs.com/javascript-this-different-contexts/
Comentaris
Publica un comentari a l'entrada