this
keyword properly. We saw that the crucial factor in determining what this
refers to, is to find out the current execution context. However, this task can be a bit tricky in situations where the context gets changed in a way we don’t expect. In this article I will highlight when this might happen and what we can do to remedy it.
Key Takeaways
- The ‘this’ keyword in JavaScript refers to the current execution context, and understanding it is crucial for manipulating and interacting with objects, especially in object-oriented programming or when using frameworks and libraries that heavily rely on ‘this’.
- Common issues with the ‘this’ keyword include its use in extracted methods, callbacks, and inside closures. These issues can be resolved by explicitly binding the ‘this’ keyword to the correct object using the bind() method.
- The ECMAScript 6 introduces the arrow function which takes the ‘this’ value from their immediate enclosing scope. This lexical binding of an arrow function can’t be overridden, making it a more elegant solution for maintaining the correct context of ‘this’.
- The value of ‘this’ depends on how a function is invoked. In a method, ‘this’ refers to the object it belongs to. In a regular function, ‘this’ refers to the global object. If a function is called with the ‘new’ keyword (as a constructor), ‘this’ refers to the newly created object. In event handlers, ‘this’ refers to the element that received the event. Lastly, ‘this’ can be explicitly set with call(), apply(), or bind().
Fixing Common Issues
In this section we’ll explore some of the most common issues arising from the use of thethis
keyword and we’ll learn how to fix them.
1. Using this
in Extracted Methods
One of the most common mistakes that people make is when trying to assign an object’s method to a variable and expecting that this
will still point to the original object. As we can see from the following example, that simply doesn’t work.
var car = {
brand: "Nissan",
getBrand: function(){
console.log(this.brand);
}
};
var getCarBrand = car.getBrand;
getCarBrand(); // output: undefined
JS Bin
Even though getCarBrand
appears to be a reference to car.getBrand()
, in fact, it’s just another reference to getBrand()
itself. We already know that the call-site is what matters in determining the context, and here, the call-site is getCarBrand()
, which is a plain and simple function call.
To prove that getCarBrand
points to a baseless function (one which isn’t bound to any specific object), just add alert(getCarBrand);
to the bottom of the code and you’ll see the following output:
function(){
console.log(this.brand);
}
getCarBrand
holds just a plain function, which is no longer a method of the car
object. So, in this case, this.brand
actually translates to window.brand
, which is, of course, undefined
.
If we extract a method from an object, it becomes a plain function again. Its connection to the object is severed, and it no longer works as intended. In other words, an extracted function is not bound to the object it was taken from.
So how can we remedy this? Well, if we want to keep the reference to the original object, we need to explicitly bind the getBrand()
function to the car
object when we assign it to the getCarBrand
variable. We can do this by using the bind() method.
var getCarBrand = car.getBrand.bind(car);
getCarBrand(); // output: Nissan
Now, we get the proper output, because we successfully redefine the context to what we want it to be.
2 this
Used in Callbacks
The next issue occurs when we pass a method (that uses this
as a parameter) to be used as a callback function. For example:
<button id="btn" type="button">Get the car's brand</button>
var car = {
brand: "Nissan",
getBrand: function(){
console.log(this.brand);
}
};
var el = document.getElementById("btn");
el.addEventListener("click", car.getBrand);
JS Bin
Even though we use car.getBrand
, we actually only get the function getBrand()
which is attached to the button
object.
Passing a parameter to a function is an implicit assignment, so what happens here is almost the same as in the previous example. The difference is that now car.getBrand
is not explicitly assigned, but implicitly. And the result is pretty much the same—what we get is a plain function, bound to the button
object.
In other words, when we execute a method on an object, which is different from the object upon which the method was originally defined, the this
keyword no longer refers to the original object, rather to the object that invokes the method.
With reference to our example: we are executing car.getBrand
on el
(the button element), not the car
object, upon which it was originally defined. Consequently, this
no longer refers to car
, rather to el
.
If we want to keep the reference to the original object intact, again, we need to explicitly bind the getBrand()
function to the car
object by using the bind()
method.
el.addEventListener("click", car.getBrand.bind(car));
Now, everything works as expected.
3 this
Used Inside Closures
Another instance when this
‘s context can be mistaken is when we use this
inside of a closure. Consider the following example:
var car = {
brand: "Nissan",
getBrand: function(){
var closure = function(){
console.log(this.brand);
};
return closure();
}
};
car.getBrand(); // output: undefined
JS Bin
Here, the output we get is undefined
, because closure functions (inner functions) don’t have access to the this
variable of outer functions. The net result is that this.brand
is equal to window.brand
, because this
in inner functions is bound to the global object.
To fix this issue, we need to keep this
bound to the getBrand()
function.
var car = {
brand: "Nissan",
getBrand: function(){
var closure = function(){
console.log(this.brand);
}.bind(this);
return closure();
}
};
car.getBrand(); // output: Nissan
JS Bin
This binding is equivalent to car.getBrand.bind(car)
.
Another popular method to fix closures, is to assign the this
value to another variable, thus preventing the unwanted change.
var car = {
brand: "Nissan",
getBrand: function(){
var self = this;
var closure = function(){
console.log(self.brand);
};
return closure();
}
};
car.getBrand(); // output: Nissan
JS Bin
Here, the value of this
can be assigned to _this
, that
, self
, me
, my
, context
, an object’s pseudo name, or whatever else works for you. The main point is to keep a reference to the original object.
ECMAScript 6 to the Rescue
In the previous example we saw a primer on what is known as “lexicalthis
“—when we set the this
value to another variable. In ECMAScript 6 we can use the similar, but more elegant, technique, applicable via the new arrow functions.
Arrow-functions are created not by the function
keyword, but by the so-called “fat arrow” operator (=>
). Unlike regular functions, arrow functions take the this
value from their immediate enclosing scope. The lexical binding of an arrow function can’t be overridden, even with the new
operator.
Let’s now see how arrow function can be used to substitute the var self = this;
statement.
var car = {
brand: "Nissan",
getBrand: function(){
// the arrow function keeps the scope of "this" lexical
var closure = () => {
console.log(this.brand);
};
return closure();
}
};
car.getBrand(); // output: Nissan
JS Bin
What You Need to Remember About this
We saw that the this
keyword, like every other mechanism, follows some simple rules, and if we know them well, then we can use that mechanism with more confidence. So, let’s quickly recap what we have learned (from this and from the previous article):
this
refers to the global object in the following cases:- in the outermost context, outside of any function block
- in functions that are not methods of objects
- in functions that are not object constructors
- When a function is called as a property on a parent object,
this
refers to the parent object. - When a function is called using
call()
orapply()
, orbind()
,this
refers to the first argument passed to these methods. If the first argument isnull
or not an object,this
refers to the global object. - When a function is called with the
new
operator,this
refers to the newly created object. - When an arrow function (introduced in ECMAScript 6) is used,
this
relies on lexical scope and refers to the parent object.
this
will point to, and if it’s not what we want, we know which methods we can use to fix it.
Summary
JavaScript’sthis
keyword is a tricky concept to master, but with enough practice, master it you can. I hope that this article and my previous article, serve as good basis for your understanding and prove to be a valuable reference the next time this
is causing you headaches.
Frequently Asked Questions (FAQs) about JavaScript’s ‘this’ Keyword
What is the ‘this’ keyword in JavaScript and why is it important?
The ‘this’ keyword in JavaScript is a special keyword that refers to the context in which a function is called. It’s a reference to the object that invoked the function. The value of ‘this’ can change depending on how a function is called, which makes it a powerful and flexible feature of JavaScript. Understanding ‘this’ is crucial for manipulating and interacting with objects, especially when working with object-oriented programming or when using frameworks and libraries that heavily rely on ‘this’.
How does the ‘this’ keyword work in different contexts?
The value of ‘this’ depends on how a function is invoked. In a method (a function inside an object), ‘this’ refers to the object it belongs to. In a regular function, ‘this’ refers to the global object (in browsers, it’s the window object). If a function is called with the ‘new’ keyword (as a constructor), ‘this’ refers to the newly created object. In event handlers, ‘this’ refers to the element that received the event. Lastly, ‘this’ can be explicitly set with call(), apply(), or bind().
What is the difference between ‘this’ in arrow functions and regular functions?
In regular functions, the value of ‘this’ is determined by how the function is called. However, arrow functions do not have their own ‘this’. Instead, they inherit ‘this’ from the parent scope at the time they are created. This makes arrow functions useful in situations where you want to preserve the context of ‘this’, such as in event handlers or callbacks.
How can I explicitly set the value of ‘this’ in a function?
JavaScript provides three methods to explicitly set the value of ‘this’ in a function: call(), apply(), and bind(). The call() and apply() methods call a function with a given ‘this’ value and arguments. The difference between them is that call() accepts an argument list, while apply() accepts a single array of arguments. The bind() method returns a new function, allowing you to specify the ‘this’ value when the function is called.
Why does ‘this’ inside a callback function refer to the global object?
When a callback function is invoked, it’s usually called as a regular function. In JavaScript, a regular function’s ‘this’ is either the global object or undefined (in strict mode). This can lead to unexpected results if you were expecting ‘this’ to refer to a different object. To work around this, you can use an arrow function for the callback (since it doesn’t have its own ‘this’), or use bind() to set the ‘this’ value.
How does ‘this’ behave in strict mode?
In strict mode, the value of ‘this’ in a function not associated with an object is undefined. This is a change from non-strict mode, where ‘this’ in a regular function refers to the global object. This change helps prevent bugs and makes code more predictable.
What is the ‘new’ keyword and how does it affect ‘this’?
The ‘new’ keyword in JavaScript is used to create an instance of an object type. When a function is called with ‘new’, it’s known as a constructor call. In a constructor call, ‘this’ refers to the newly created object. This allows you to add properties or methods to the object within the constructor function.
How does ‘this’ work in event handlers?
In event handlers, ‘this’ refers to the HTML element that received the event. This allows you to directly interact with the element within the event handler function. For example, you can change the element’s properties, call its methods, or access its child elements.
Can I use ‘this’ in object methods?
Yes, ‘this’ is commonly used in object methods. In a method, ‘this’ refers to the object it belongs to. This allows you to access and manipulate the object’s properties within the method.
What are some common pitfalls when using ‘this’ in JavaScript?
One common pitfall is assuming that ‘this’ within a function always refers to the function itself. In fact, ‘this’ refers to the object that invoked the function. Another common pitfall is using ‘this’ in a callback function or an event handler, where ‘this’ may not refer to what you expect. Understanding how ‘this’ works in different contexts and how to control its value can help avoid these pitfalls.
I am a web developer/designer from Bulgaria. My favorite web technologies include SVG, HTML, CSS, Tailwind, JavaScript, Node, Vue, and React. When I'm not programming the Web, I love to program my own reality ;)