DEV Community

DNelson35
DNelson35

Posted on • Edited on

How "this" Works

About "this"

The this keyword in JavaScript could be considered one of its more difficult concepts to grasp. To better understand this, we first need to know what this is. The simple definition of this is that this refers to the object that is executing the current function. We should also note that JavaScript is an object-oriented language. It's important to know this because in JavaScript, this is used to refer to the current object or to the current event. While this may seem easy to understand, this can be more difficult in practice. The value of this may vary depending on how the function containingthis is called and executed. This has to do with the execution context of the function. For example if we where to write

function whatsThis(){
    console.log(this)
}

whatsThis(); // => window obj.
Enter fullscreen mode Exit fullscreen mode

As we can see this in this context is referring to the window obj. It may seem like the value of this should be the function itself, but remember that the value of this is the object which is executing the function never the function itself. In this case the object that is executing the function is the global object. The reason is when the function is being declared inside the global scope, it is not nested inside of a "parent" obj so it refers to the global obj which is the window. The purpose of this blog will be to explain how this changes depending on when and where it is used.

Working With 'this'

We seen above how this used in a stand alone function binds to the window object, but how can we get this to work for us. One way would be to call a function as a method of an object. for example

const player = {
name: 'Jack',
func: function(){
   console.log(`Hello ${this.name} do you want to play a game?`);
 }
}

player.func() // => 'Hello Jack do you want to play a game?'
Enter fullscreen mode Exit fullscreen mode

In this example, this is bound to the player Object, essentially this === player. This is called Implicit binding, we will talk about binding this in the next section. For now, let's think about why this is the player and not the window. before, when we tried to use this, we used this in a stand alone function. The stand alone function was declared in the global context. Now we defined the function as a method of player. puting the function (func) inside the context of player so the object calling the function now is not the window but the player object. but we still need to be careful. Take a look at this example.

const person = {
  name: 'Sam',
  sayName: function() {
    console.log(`My name is ${this.name}`);
  }
};

const sayName = obj.sayName;

sayName(); // outputs "My name is undefined", because "this" is the window object

Enter fullscreen mode Exit fullscreen mode

This may be confusing because sayName is defined as a method of the person object, but we are getting undefined. Well, this is happening because when we call sayName as a standalone function the value of this becomes the window again. That is do to the fact that the function is no longer being called as a method of the person object. At this point, it might not seem like this has a purpose. Why would we need this if it can only be used inside the object? What is the point? To answer those questions we need to talk about binding.

Binding this

There are several ways to use this, and there are different ways to bind this. above we already discussed two types of binding "implicit binding", and "Window binding" but there are Two other types of binding. Let's take a deeper look at each of them.

Implicit Binding

Implicit binding is when a function is called as a method of an object, this is bound to the object that the function is a method of. like in the example above.

Explicit Binding

Explicit binding is when we use the methods 'call', 'apply', and 'bind', and we explicitly bind this to a object. for example:

const greet = function(greeting) {
  console.log(`${greeting}, my name is ${this.name}`);
}

const person1 = { name: 'John' };
const person2 = { name: 'Jane' };

greet.call(person1, 'Hello'); // Output: "Hello, my name is John"
greet.apply(person2, ['Hello']); // Output: "Hello, my name is Jane"

const boundGreet = greet.bind(person1);
boundGreet('Hello'); // Output: "Hello, my name is John"

Enter fullscreen mode Exit fullscreen mode

In the example above, we see that when we use these methods we can change what this is bound to. This brings us out of only being able to use this in side of the object we define the function in. we can now bind a function to any object and the return value of this will become the object it is bound to, like in the example.

New Binding

New binding is when a function is called using the new keyword, this is bound to the newly created object. for example:

function Person(name) {
  this.name = name;
}

const person = new Person('John');
console.log(person.name); // Output: "John"
Enter fullscreen mode Exit fullscreen mode

This is called a constructor function. when we use a constructor function each new obj will have this bound to the person object created by the function above.

With the knowledge of the different ways to bind this to an object, or even how to create an object using this. We can now see that the this keyword has multiple uses, and can be used to both simplify and expand our code in useful ways.

Arrow Functions With this

When it comes to arrow functions they use this a bit differently. Because arrow functions do not define its own this context they inherit the context of the parent function. Now that may sound similar to what we discussed previously, but its not. What this means is that if we use an arrow function it will look for the next function with context not object. Before when we declare the function as a method the function tells this to bind to the object executing the function. With arrow functions this does not happen. here is an example of how an arrow function would handle being declared as a method on its own.

const person = {
  name: 'Tim',
  sayName: () => {
    console.log(this.name);
  }
};

obj.sayName(); // outputs 'undefined', because "this" is the window object
Enter fullscreen mode Exit fullscreen mode

Before when we did this with a anonymous function, the function told this to bind to the object executing it, person. Now with an arrow function the function is not telling this to bind to the object so this looks for the next function with context and that is the window. and since window has no name property it returns undefined. Next let's look at an example of how we can get this to work with an arrow function like the one above.

const person = {
  name: 'Tim',
  sayName: function() {
    const innerFunc = () => {
      console.log(this.name);
    };
    innerFunc();
  }
};

person.sayName(); // => 'Tim'
Enter fullscreen mode Exit fullscreen mode

In this example we get the response we are looking for. The reason is because the arrow function looks for the next function with context, in this case it is the anonymous function the arrow function is nested in. Then, this takes on the value of the object calling the anonymous function like we have seen before.

Conclusion

Yes this can be a very complicated topic to grasp. Once we are able to understand this we not only gain access to a extremely beneficial tool, we also gain a better understanding of how javascript operates. We gain a better understanding of context and object oriented programing. Not only simplify solutions but come up with new and unique ways to accomplish task.

Top comments (0)