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.
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?'
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
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"
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"
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
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'
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)