I Finally Understood JavaScript's this Keyword (And You Can Too!)

Hi! I’m an aspiring Frontend Developer currently pursuing my Bachelor of Computer Applications (LPU)
Okay, let me be real with you. JavaScript this keyword was my biggest enemy for weeks. I'd write what I thought was perfect code, run it and get completely unexpected results. Sound familiar?
I probably watched couple of YouTube tutorials and read 2-3 blog posts. Most of them helped a tiny bit, but I was still super confused. Then I found this one YouTube video (I'll link it at the end) that completely changed how I think about this.
What Even Is this?
At its core, this is a special keyword in JavaScript that points to an object. But which object? That’s the whole mystery.
The most important thing to remember is this:
The value of this is not determined by where the function is written, but by how the function is called.
This is different from regular variables, which depend on their location in the code (their "scope"). this is all about context.
A good analogy is the word "me." Who "me" refers to depends entirely on who says it. If I say "me," I'm talking about myself. If you say "me," you're talking about yourself. this works the same way.
The Four Rules of this (Your New Cheat Code)
Figuring out what this actually points to can feel tricky, but it really comes down to four simple rules. Let’s break them down.
1. Implicit Binding (The Most Common Rule)
This is the easiest rule. Look to the left of the dot.
When you call a function as a method of an object (using a dot .), this becomes the object left of that dot.
const myCat = {
name: "Whiskers",
meow: function() {
console.log(`${this.name} says meow!`);
}
};
myCat.meow(); // "Whiskers says meow!"
// The object left of the dot (.) is `myCat`, so `this` = `myCat`
Simple, right? The function meow is called with myCat as its context, so inside it, this is myCat.
2. Explicit Binding (Forcing this to Be What You Want)
What if a function isn't attached to an object? How do you tell it what this should be? You explicitly set it using call(), apply(), or bind().
These are methods available on all functions.
call()andapply(): Immediately run the function, settingthisto the first argument you pass in.bind(): Returns a brand new function withthispermanently locked to your value. This is a lifesaver for callbacks.
function describeFood(food) {
console.log(`${this.name} loves to eat ${food}`);
}
const person = { name: "rahman" };
const dog = { name: "Rex" };
// Use call() or apply() to immediately run it
describeFood.call(person, "pizza"); // "rahman loves to eat pizza"
describeFood.apply(dog, ["kibble"]); // "Rex loves to eat kibble"
// Use bind() to create a new function for later
const rexsFunction = describeFood.bind(dog, "kibble");
rexsFunction(); // "Rex loves to eat kibble" (whenever you call it)
With explicit binding, you are in control.
3. The new Binding (For Constructor Functions)
When you create an object using the new keyword (like new Date()), something special happens. this inside that constructor function refers to the brand new object being created.
function User(name, age) {
// `this` is the new blank object being created
this.name = name;
this.age = age;
// The function automatically returns `this` (the new object)
}
const user1 = new User("rahman", 25);
console.log(user1.name); // "rahman"
// Inside the `User` function when called with `new`, `this` was the new object.
4. The Default Binding (The Last Resort)
If none of the other rules apply, JavaScript falls back to the default binding.
In regular mode:
thispoints to the global object (windowin browsers). This is usually a bad thing and can cause bugs!In strict mode (
'use strict';):thisbecomesundefinedto prevent those bugs.
function globalFunction() {
console.log(this); // In a browser, logs the giant `window` object
}
globalFunction(); // No object left of the dot, no `new`, no explicit binding.
// So it uses the default rule.
The Special Case: Arrow Functions 😁😁
Arrow functions (() => {}) are the cool new kids on the block, and they break the rules! Arrow functions do not have their own this.
Instead, they ignore all the rules above and simply inherit the this value from their parent scope (the place where they were written). This makes them incredibly useful for things like callbacks and event handlers.
const myObject = {
name: "My Object",
traditionalMethod: function() {
console.log("Traditional:", this.name); // "Traditional: My Object" (Rule 1)
},
arrowMethod: () => {
console.log("Arrow:", this.name); // "Arrow: " (probably undefined!)
// It inherits `this` from the global scope here, not from myObject.
}
};
myObject.traditionalMethod();
myObject.arrowMethod();
See the difference? Use arrow functions when you want this to be predictable and not change based on how the function is called.
A Common Problem (And How to Fix It)
One of the most common ways to lose your this context is when passing a method as a callback, like to setTimeout.
const student = {
name: "rahman",
study: function() {
console.log(`${this.name} is studying hard!`);
}
};
// This will break! The function gets passed alone, losing its connection to `student`.
setTimeout(student.study, 1000); // " is studying hard!"
The Fix: Use bind() or an arrow function to lock the context.
// Fix 1: Use bind()
setTimeout(student.study.bind(student), 1000);
// Fix 2: Wrap it in an arrow function
setTimeout(() => {
student.study(); // Now it's called with the object, so Rule 1 applies!
}, 1000);
The Key Insight
this depends on HOW you call the function, not WHERE you write it.
Once I stopped trying to memorize rules and started looking at how each function was called, everything became clear.
The Video That Changed Everything
I promised I'd share that YouTube video - [Watch Now]. The creator explained it so simply with easy examples. Definitely worth watching!
I hope this helps clear things up! It definitely helped me to write it all down. If you see any mistakes in my logic (very possible, I'm still learning!), please let me know. Let's figure this stuff out together.



