about 1 year ago

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).

← JavaScript bind, call and apply JavaScript __proto___ and Function.prototype →
 
comments powered by Disqus