What is this keyword
The this keyword is one of the most powerful and sometimes confusing concepts in JavaScript. It refers to the context in which the current code is executing, and its value can vary depending on how and where it is used.
Or this in JavaScript usually refers to the object that invoked the function, but its value depends on how and where the function is called.
this in the Global Context
In the global context, this refers to the global object. In a browser, the global object is the window. This behavior is consistent whether you are in a script tag or a standalone JavaScript file. However, there are differences when this is used in strict mode, which is explained below.
In non-strict mode, this always refers to the global object.
// Global scope
console.log(this); // Logs the window object in a browser
Strict ModeIn strict mode ("use strict";), the value of this in the global context is undefined instead of the global object. This is a safeguard to prevent unintended behaviors.
"use strict";
// Global scope
console.log(this); // Logs undefined in strict mode
This distinction between strict and non-strict modes is crucial for writing predictable and bug-free code, especially when working in different environments like Node.js or browsers.
this Inside a Regular Function
Inside a regular function, the value of this depends on whether the function is executed in strict mode or non-strict mode. Understanding this distinction is key to avoiding unexpected results.
In non-strict mode, this inside a regular function refers to the global object (window in browsers). This behavior is the default if strict mode is not explicitly enabled.
function showThis() {
console.log(this); // Logs the window object in browsers
}
showThis();Strict ModeIn strict mode ("use strict";), the value of this inside a regular function is undefined. This is a safety mechanism to avoid accidental modifications to the global object.
"use strict";
function showThis() {
console.log(this); // Logs undefined in strict mode
}
showThis();Using this in Nested Functions
When a regular function is nested inside another function, the value of this depends on the same rules. In non-strict mode, this refers to the global object. However, in strict mode, it remains undefined.
"use strict";
function outerFunction() {
function innerFunction() {
console.log(this); // Logs undefined in strict mode
}
innerFunction();
}
outerFunction();this Inside an Object Method
When this is used inside an object's method, it typically refers to the object that owns the method. This allows methods to access other properties or methods of the same object.
In the example below, this refers to the object obj. Using this, the method can access the object's properties.
const obj = {
name: "Prakash",
greet() {
console.log(this.name); // "Prakash"
},
};
obj.greet();Dynamic Behavior of this
The value of this inside an object's method can change depending on how the method is called. If the method is assigned to a variable and then called, this will no longer refer to the original object.
const obj = {
name: "Prakash",
greet() {
console.log(this.name);
},
};
const greetFn = obj.greet;
greetFn(); // undefined, because this refers to the global object (non-strict mode) or undefined (strict mode)this with Arrow Functions
Arrow functions do not have their own this; instead, they inherit this from the surrounding lexical scope. This means that using an arrow function as a method will not work as expected because this will not refer to the object.
const obj = {
name: "Prakash",
greet: () => {
console.log(this.name);
},
};
obj.greet(); // undefined, because this does not refer to objBest Practices- Use regular functions for object methods to ensure
thisrefers to the object. - Be cautious when using object methods in callbacks or assigning them to variables. Use
.bind(),call(), orapply()to explicitly set the value ofthisif needed.
const obj = {
name: "Prakash",
greet() {
console.log(this.name);
},
};
const boundGreet = obj.greet.bind(obj);
boundGreet(); // "Prakash"Note : We will study call, apply, bind in details later.
Arrow functions do not have their own this. Instead, they inherit this from their enclosing lexical scope at the time they are defined. This behavior makes arrow functions particularly useful in cases where preserving the outer this is important, such as in callbacks.
In the example below, the arrow function inside the object obj does not bind its own this. As a result, this refers to the outer context, which is the global object in non-strict mode or undefined in strict mode.
const obj = {
name: "Prakash",
greet: () => {
console.log(this.name); // undefined because this refers to the global object.
},
};
obj.greet();Arrow Functions in Nested Methods
Arrow functions are often used to avoid explicitly binding this when using callbacks or nested functions, as they automatically inherit this from their enclosing scope.
const obj = {
name: "Prakash",
greet() {
const arrowFn = () => {
console.log(this.name); // "Prakash", because this refers to the enclosing context (greet method).
};
arrowFn();
},
};
obj.greet();Comparison with Regular Functions
Regular functions create their own this, which depends on how the function is called. Arrow functions, however, do not have this ambiguity since they always use this from the surrounding scope.
const obj = {
name: "Prakash",
regularFn: function() {
console.log(this.name); // "Prakash" when called as obj.regularFn()
},
arrowFn: () => {
console.log(this.name); // undefined because this refers to the global object.
},
};
obj.regularFn();
obj.arrowFn();Best Practices- Use arrow functions in cases where you need to preserve
thisfrom the enclosing scope, such as callbacks or nested functions. - Avoid using arrow functions as methods inside objects, as
thiswill not refer to the object. - Use regular functions for methods when you need
thisto refer to the object.
this with Constructor Function
When used in a constructor function, this refers to the newly created object. Constructor functions are special functions used to initialize objects. They are invoked with the new keyword, which creates a new object and sets this to point to that object.
A constructor function is defined like a regular function, but it is intended to be called with the new keyword. Inside the function, this is used to set properties or methods on the newly created object.
function Person(name) {
this.name = name; // 'this' refers to the newly created object
}
const prakash = new Person("Prakash");
console.log(prakash.name); // "Prakash"How Constructor Functions Work- When a constructor function is called with
new, a new empty object is created. - The constructor function's
thisis set to the new object. - Properties and methods can be added to the new object using
this. - The new object is automatically returned unless the constructor explicitly returns a different object.
function Person(name) {
this.name = name;
this.greet = function () {
console.log("Hello, my name is " + this.name);
};
}
const prakash = new Person("Prakash");
prakash.greet(); // "Hello, my name is Prakash"Note:Constructor functions are a fundamental concept in JavaScript for creating objects, but modern JavaScript often uses classes as a cleaner, more structured way to achieve the same functionality.
class Person {
constructor(name) {
this.name = name; // 'this' refers to the newly created object
}
greet() {
console.log("Hello, my name is " + this.name);
}
}
const prakash = new Person("Prakash");
prakash.greet(); // "Hello, my name is Prakash"Key Pointsthisin a constructor refers to the object being created.- Always use the
newkeyword when calling a constructor function to ensurethisworks as expected. - Constructor functions are a precursor to ES6 classes, which simplify object-oriented programming in JavaScript.
Note : We will study class & Object later.
this Inside setTimeout
The behavior of this inside setTimeout depends on how the function is called. In regular functions, this loses its reference to the original object because the function is executed in the global scope.
this inside setTimeoutIn the example below, this inside setTimeout does not refer to objbut to the global object (or undefined in strict mode).
const obj = {
name: "Prakash",
greet() {
setTimeout(function () {
console.log(this.name); // Undefined or Error in strict mode
}, 1000);
},
};
obj.greet();Fixing this Inside setTimeoutTo retain the correct reference to this, we can use an arrow function. Arrow functions do not bind their own this; instead, they inherit it from the enclosing scope.
In this example, this inside setTimeout correctly refers to obj.
const obj = {
name: "Prakash",
greet() {
setTimeout(() => {
console.log(this.name); // "Prakash"
}, 1000);
},
};
obj.greet(); Alternative Fix: Using bind()To maintain the correct reference to this, we use .bind(this). This explicitly binds this inside the function to the object obj.
bind(this)const obj = {
name: "Prakash",
greet() {
setTimeout(function () {
console.log(this.name); // "Prakash"
}.bind(this), 1000);
},
};
obj.greet();How bind(this) Works?- The
bind()method creates a new function that hasthispermanently set to the object that called it. - In this case,
bind(this)ensures thatthisinsidesetTimeoutrefers toobjinstead of the global object. - Now,
this.namecorrectly refers to"Prakash".
this in Event Listeners
In event listeners, this typically refers to the element on which the event listener is added. However, the behavior of this can vary depending on whether the handler is a regular function or an arrow function.
When a regular function is used in an event listener, this refers to the element that triggered the event.
document.querySelector("button").addEventListener("click", function () {
console.log(this); // Refers to the button element
});Arrow Function in Event ListenerArrow functions do not bind their own this. Instead, they inherit this from the surrounding lexical scope. This means this does not refer to the element that triggered the event, but rather to the context in which the arrow function was defined.
document.querySelector("button").addEventListener("click", () => {
console.log(this); // Refers to the outer lexical scope (e.g., window in global context).
});Using this with Event DelegationEvent delegation relies on attaching a single event listener to a parent element, which handles events for its child elements. In such cases, this refers to the parent element where the event listener is attached, but you can use event.target to determine the specific child element that triggered the event.
document.querySelector("ul").addEventListener("click", function (event) {
console.log(this); // Refers to the <ul> element
console.log(event.target); // Refers to the child element (e.g., <li>) that triggered the event
});Key Points- When using regular functions in event listeners,
thisrefers to the element that triggered the event. - Arrow functions do not bind
thisto the element; instead, they inheritthisfrom the outer lexical scope. - For event delegation,
event.targetis often used alongsidethisto identify the specific element that triggered the event.
Key Takeaways
The value of this in JavaScript depends on the execution context. By understanding these contexts and how this behaves in each, you can write more predictable and maintainable code.