Understanding the this Keyword in JavaScript
Let's Actually Understand this in JavaScript

If there's one thing that confuses JavaScript developers more than anything else, for beginner and experienced both it's this.
It looks simple. But it behaves differently depending on where you use it, how you call a function, and sometimes even whether you're in strict mode or not.
By the end of this, you'll stop guessing what this is. You'll know.
Thumb Rule
Before any examples, here's the single most important thing to understand about this:
thisis not about where a function is defined. It's about who calls it.
Read that again. Burn it in.
Most this confusion comes from thinking that this is locked to the function at the time you write it. It isn't. this is decided at the moment the function is called based on what's to the left of the dot.
That's the whole secret. Everything else is just variations of that rule.
Visualizing Caller to Function Relationship
Think of every function call as a conversation. Someone calls the function. That someone is this.
Same function. Different caller. Different this. That's the whole game.
this in the Global Context
When you open a JavaScript file and write this outside of any function or object, it refers to the global object.
In a browser, that's window. In Node.js, that's global.
console.log(this); // window (in browser)
function showThis() {
console.log(this); // also window — no caller, so global is assumed
}
showThis();
Think of the global object as the default owner of everything. When there's no specific caller, the global context steps in.
In strict mode, this changes:
"use strict";
function showThis() {
console.log(this); // undefined — strict mode removes the global fallback
}
showThis();
This is a common gotcha. Strict mode is more honest it says there's no caller here, so this is nothing instead of quietly pointing to window.
this Inside Objects
This is where this starts feeling genuinely useful.
When a function lives inside an object and you call it through that object, this refers to the object itself.
const user = {
name: "Satpal",
greet: function() {
console.log("Hello, " + this.name);
}
};
user.greet(); // Hello, Satpal
user is to the left of the dot. So this inside greet is user. JavaScript looks left of the dot — that's what this gets set to.
Multiple methods sharing this:
const counter = {
count: 0,
increment: function() {
this.count++;
},
reset: function() {
this.count = 0;
},
show: function() {
console.log("Count:", this.count);
}
};
counter.increment();
counter.increment();
counter.show(); // Count: 2
counter.reset();
counter.show(); // Count: 0
Every method can talk to the same object's data through this. That's exactly what makes objects useful shared state with methods that can read and change it.
How Calling Context Changes this
Here's where most developers get burned. The same function can produce completely different this values depending on how it's called.
const user = {
name: "Riya",
greet: function() {
console.log(this.name);
}
};
user.greet(); // "Riya" — called on user, this = user
const fn = user.greet;
fn(); // undefined — called alone, this = window
You didn't change the function. You just changed how you called it. The moment you detach a method from its object, it loses its this.
This catches people constantly especially when passing methods as callbacks:
const user = {
name: "Arjun",
greet: function() {
console.log("Hello,", this.name);
}
};
setTimeout(user.greet, 1000); // Hello, undefined 😬
user.greet got handed to setTimeout. When setTimeout calls it, there's no user. in front — so this is lost.
Here's the full picture of how context shifts across four common situations:
For global:
For Object:
Regular Function:
Arrow Function:
this Inside Regular Functions
A standalone function called without any object in front of it follows the global fallback rule.
function showThis() {
console.log(this);
}
showThis(); // window (browser) or undefined (strict mode)
No dot. No owner. Global takes over or undefined in strict mode.
Nested functions lose this too:
const user = {
name: "Priya",
greet: function() {
console.log(this.name); // "Priya" — works fine
function inner() {
console.log(this.name); // undefined — inner lost the context
}
inner();
}
};
user.greet();
inner() is called without a dot. Even though it's inside a method, it doesn't inherit this. Each function has its own this determined by how it's called not where it's written.
The Full Picture
Here's every context in one place:
| How it's called | What this is |
|---|---|
fn() in global |
window (or undefined in strict mode) |
obj.fn() |
obj — whatever is left of the dot |
fn.call(x) |
x — explicitly set |
fn.apply(x) |
x — explicitly set |
fn.bind(x)() |
x — permanently locked |
new fn() |
the newly created object |
| Arrow function | this from surrounding scope at definition |
| Event listener (regular fn) | the DOM element that fired the event |
| Event listener (arrow fn) | outer this, not the element |
"Programs must be written for people to read, and only incidentally for machines to execute."
--Harold Abelson






