Understanding the this Keyword in JavaScript

JavaScript’s this keyword is one of the most commonly misunderstood concepts, not because it is complex, but because it behaves differently depending on how a function is called. The simplest and most accurate way to understand this is it refers to the caller of the function. Once you adopt this mental model, most confusion disappears.
This article explains this step by step using practical examples, avoiding unnecessary internal details.
What this Represents
At its core, this is a reference to the object that is currently executing the function. It is not fixed when the function is written—it is determined at runtime based on how the function is invoked.
this in Global Context
When code runs at the top level (not inside any function), this refers to the global object.
In browsers:
console.log(this); // window
So in a browser environment, this === window. But in strict mode implicit binding implemented to avoid bugs. This difference matters when debugging unexpected this values.
this Inside Objects
When a function is called as a method of an object, this refers to that object.
Example:
const user = {
name: "Pritam",
greet() {
console.log(this.name);
}
};
user.greet(); // Pritam
Breaking the Reference
If you extract the function and call it separately:
const greetFn = user.greet;
greetFn();
Output:
undefined
Now that the function is called without an object, this is no longer user.
this Inside Functions
When a normal function is called independently:
function show() {
console.log(this);
}
show();
In non-strict mode:
window
In strict mode:
undefined
Arrow Functions and this
Arrow functions behave differently. They do not have their own this. Instead, they inherit this from the surrounding scope.
Example:
const user = {
name: "Pritam",
greet: () => {
console.log(this.name);
}
};
user.greet(); // undefined
Arrow function does not bind this to user. It takes this from where it was defined (global scope).
Correct Usage:
const user = {
name: "Pritam",
greet() {
const inner = () => {
console.log(this.name);
};
inner();
}
};
user.greet(); // Pritam
How Calling Context Changes this
This is the most important part. The value of this changes based on how the function is called, not how it is written.
1. Method Call
const obj = {
value: 10,
getValue() {
return this.value;
}
};
obj.getValue();
→ this = obj
2. Function Call
const fn = obj.getValue;
fn();
→ this = window (or undefined in strict mode)
3. Using call
function greet() {
console.log(this.name);
}
const person = { name: "Pritam" };
greet.call(person);
Output:
Pritam
Here call() explicitly sets this.
4. Using apply
Same as call, but arguments are passed as an array:
greet.apply(person);
5. Using bind
const boundFn = greet.bind(person);
boundFn();
Output:
Pritam
bind returns a new function with fixed this.
Common Mistakes
1. Losing this in callbacks
const user = {
name: "Pritam",
show() {
setTimeout(function () {
console.log(this.name);
}, 1000);
}
};
user.show();
Output:
undefined
Fix with arrow function:
setTimeout(() => {
console.log(this.name);
}, 1000);
2. Using arrow functions as methods
Avoid:
const obj = {
name: "Test",
show: () => console.log(this.name)
};
Because this won’t refer to obj.
Conclusion
Most bugs related to this come from losing the calling context. Instead of focusing on JavaScript internals, focus on how the function is invoked in real code paths. That perspective scales better in real-world applications, especially when working with event handlers, callbacks, and frameworks.






