Understanding the 'this' Keyword in JavaScript

What exactly is 'this'?
In JavaScript, this is a keyword that refers to the object it belongs to. The specific object it references depends entirely on how the current function is being called. Its behavior is dynamic, meaning its value changes depending on the context in which it's used.
Common Scenarios for 'this'
1. Global Context
In the global execution context (outside of any function), this refers to the global object. In a browser, the global object is window, so this in a global context would refer to window.
console.log(this)
//output: Window {0: global, window: Window, self: Window, document: document, name: '', location: Location, …}
2. In a Regular Function
In a regurlar function call, this refers to the global object (in non-strict mode) or undefined (in strict mode).
'strict' mode
In 'strict' mode, this inside regular functions that are not part of an object will be undefined, preventing accidental reference to the global object.
function whatsThis() {
console.log(this);
}
whatsThis(); //output: Window {0: global, window: Window, self: Window, document: document, name: '', location: Location, …}
3. In an Object Method
When used inside a method belonging to an object, this refers to the object itself.
const person = {
name: "Alice",
greet: function() {
console.log("Hello, " + this.name);
}
};
person.greet(); // Output: "Hello, Alice"
Understanding Function Borrowing
When a function is assigned to a variable or another object, this will refer to the object it is called with, not where it was originally defined.
const person = {
name: "Bob",
greet: function() {
console.log("Hello, " + this.name);
}
};
const greetFunc = person.greet;
const person2 = { name: "Charlie", greet: greetFunc };
person2.greet(); // Logs "Hello, Charlie"
In the above example, when greet is called as a method of person2, this within the greet function now refers to person2, because greet is being called with person2 as the context. Therefore, this.name is "Charlie", and the function logs "Hello, Charlie" to the console.
The crucial point in this example is understanding that the value of this inside a function depends on the object it is called upon, not where the function was defined or assigned. When greetFunc is called as part of person2, this refers to person2, resulting in "Hello, Charlie" being logged.
3. In a Constructor Function
When a function is used as a constructor (with the new keyword), this refers to the newly created object.
function Person(name) {
this.name = name;
}
const person = new Person('John');
console.log(person.name); //Output: "John"
4. In a Event Listener
In event listeners, this usually refers to the HTML element that triggered the event.
const button = document.querySelector("button");
button.addEventListener("click", function() {
console.log(this); // Output: the button element
});
Arrow Functions and 'this'
We know that this within a function depends on how the function is called. Traditional functions (declared with the function keyword) have their this value set dynamically at the time they are invoked. This means that the same function can have different this values depending on its calling context.
However, arrow functions, behave differently. They do not have their own this binding. Instead, they "inherit" the this value from the lexical scope in which they were defined. This means the value of this inside an arrow function is the same as the value of this in the outer function or global scope (if not defined inside a function) where the arrow function was created.
Example 1 ->
const obj = {
show: () => {
console.log(this);
}
};
obj.show(); // In a browser, 'this' will log 'window' because it's captured from the global scope
Example 2 ->
const person = {
name: 'Alex',
activities: ['run', 'jump', 'throw'],
showActivities: function() {
this.activities.forEach((activity) => {
// Arrow function inherits 'this' from showActivities method context
console.log(`${this.name} likes to ${activity}`);
});
}
};
person.showActivities();
// Output:
// Alex likes to run
// Alex likes to jump
// Alex likes to throw
In this example, the arrow function passed to forEach inherits the this value from the showActivities method's context. Therefore, this.name inside the arrow function correctly refers to person.name
Conclusion
Since this is so context-dependent, it's sometimes a source of confusion. Always be mindful of the context in which your functions are being called to understand the value of this. Using console.log(this) is a great debugging tool.




