JS Fundamentals #17 Understanding this in JavaScript: A Complete Guide with Examples
The this keyword in JavaScript is one of the most misunderstood concepts, yet it's fundamental to writing effective code. It refers to the execution context and behaves differently depending on how a function is called.
In this article, you'll learn:
✔️ What this refers to in different contexts.
✔️ Key rules governing this.
✔️ Practical examples to solidify your understanding.
What is this?
this is a special keyword that points to an object—the one currently executing the code. Its value depends entirely on how a function is called, not where it's defined.
Rules of this in JavaScript (The 5 Key Scenarios)
Here are the five most common scenarios where this behaves differently:
1. Default Binding (Global or undefined in Strict Mode)
When used in a regular function (not an object method or event),
thisrefers to:window(in browsers) in non-strict mode.undefinedin strict mode.
Example (Non-strict mode):
function sayHello() {
console.log(this); // window (global object in browser)
}
sayHello();
Example (Strict mode):
"use strict";
function sayHello() {
console.log(this); // undefined
}
sayHello();
2. Implicit Binding (this in Object Methods)
- When a function is called as a method of an object,
thisrefers to the object itself.
Example:
const user = {
name: "Alice",
greet() {
console.log(`Hello, ${this.name}!`); // `this` = user
},
};
user.greet(); // "Hello, Alice!"
⚠️ Pitfall: If you extract the method (e.g., const greetFunc = user.greet), this may get lost!
❓ What’s wrong?
You saved the function to a new variable
greetFuncNow you're calling it without an object, so it's just a plain function call
In strict mode,
thisbecomesundefinedIn non-strict mode,
thisbecomes the global object (windowin browsers)SO this line console.log(
Hello, ${this.name}!);Will try to access: undefined.name → causes error or prints "Hello, undefined!"
How to fix this: const greetFunc = user.greet.bind(user); greetFunc(); // "Hello, Alice!"
3. Explicit Binding (Forcing this with call, apply, bind)
You can force what
thisrefers to using:func.call(obj, args)→ Callsfuncwithobjasthis.func.apply(obj, [args])→ Same ascallbut takes an array of args.func.bind(obj)→ Returns a new function permanently bound toobj.
Example (call and apply):
function introduce(lang) {
console.log(`${this.name} codes in ${lang}.`);
}
const dev = { name: "Bob" };
introduce.call(dev, "JavaScript"); // "Bob codes in JavaScript."
introduce.apply(dev, ["Python"]); // "Bob codes in Python."
Example (bind):
const boundFunc = introduce.bind(dev, "TypeScript");
boundFunc(); // "Bob codes in TypeScript."
4. new Binding (this in Constructor Functions & Classes)
- When a function is called with
new,thisrefers to the newly created instance.
Example (Constructor Function):
function Person(name) {
this.name = name;
console.log(this); // Person { name: "Charlie" }
}
const person = new Person("Charlie");
Example (Class Syntax):
class User {
constructor(name) {
this.name = name;
}
greet() {
console.log(`Hi, I'm ${this.name}.`);
}
}
const user = new User("Dana");
user.greet(); // "Hi, I'm Dana."
5. Arrow Functions (Lexical this)
Unlike normal functions, arrow functions don’t have their own
this.They inherit
thisfrom their parent scope.
Example:
const obj = {
name: "Eve",
greet: () => {
console.log(`Hi from ${this.name}.`); // `this` ≠ obj!
}
};
obj.greet(); // "Hi from undefined." (inherits global/undefined `this`)
✅ Good Use Case for Arrow Functions (Event Handlers):
class Button {
constructor() {
this.button = document.querySelector("button");
this.button.addEventListener("click", () => {
console.log(this); // `this` = Button instance
});
}
}
Common Pitfalls & Fixes
Problem: Losing this in Callbacks
const user = {
name: "Frank",
greet() {
setTimeout(function() {
console.log(`Hello, ${this.name}!`); // `this` = window/undefined
}, 1000);
}
};
user.greet(); // "Hello, !"
✅ Fix: Use an arrow function to preserve this:
setTimeout(() => {
console.log(`Hello, ${this.name}!`); // `this` = user (lexically bound)
}, 1000);
or bind:
setTimeout(function() {
console.log(`Hello, ${this.name}!`);
}.bind(user), 1000);
Summary of this Rules
| Scenario | What this refers to |
| Default Binding | window (non-strict) / undefined (strict) |
Method Call (obj.func()) | The object (obj) |
Explicit Binding (call, apply, bind) | The provided object (obj) |
new Binding (new Class()) | The newly created instance |
| Arrow Functions | Inherited from parent scope |
Final Thoughts
The this keyword is context-dependent, but once you understand the core rules, it becomes easy to predict. Key takeaways:
☑️ Use
call/apply/bindfor explicit control.☑️ Arrow functions inherit
this(=>≠function).☑️
newcreates a newthisobject.