The value of this
depends on how the function is called. There are four ways to call a function:
- function invocation
- method invocation
- constructor invocation
- apply/call invocation
Function Invocation
function add(){
console.log(this); // Window object
}
add(); // function invocation
In this case, this
inside the function add
is always bound to the global variable of the environment. (It is the Window object in this case because I run the code inside a browser)
A special case of function invocation is closure:
function add(){
function plus(){
console.log(this); // Window object
}
plus(); // function invocation
}
add(); // function invocation
It is tempting to think the this
value inside the plus()
function is tied to add
. However, that is not the case as it is explained in this post. plus
is still triggered via function invocation, so this
still points to the global variable.
Method Invocation
var person = {
name: 'John',
sayName: function(){
console.log(this.name);
}
}
person.sayName(); // Method invocation, which output "John"
When ever the dot notation is used, a method invocation happens. In this case, the value of this
equals to the object before the dot. So in this case, this == person
. Because person.name = "John"
, this.name == "John"
.
A special case is nested objects:
var foo = {
bar: {
sayName: function() {...}
}
}
foo.bar.sayName(); // this == bar not foo
whoever is closest to the function call is the value of this
.
Constructor Invocation
function Person(){
this.name = 'John'
}
console.log((new Person()).name); // Constructor invocation, outputs "John"
In this case, a new object has been created. The keyword this points to the newly created object. The function setName()
is equivelent to the following code:
function Person() {
var this = {}; // this is not valid, just for illustration
this.__proto__ = Person.prototype;
this.name = 'John’
return this;
}
Apply/Call Invocation
By using Apply
or Call
(or bind
), you can specify the value of this
:
function setName() {
this.name = "John";
}
setName(); // function invocaiton
console.log(this.name); // John
console.log(window.name); // John
var p1 = {};
setName.apply(p1); // apply invocation
console.log(p1.name); // John
When setName()
is called the first time, name
is created on the window
object. If we want to attach the name property to a different object, we can use apply or call (or bind).