This Keyword in JS
Source: Dev.to
Introduction
The this keyword in JavaScript often confuses both junior and senior developers.
Understanding this depends not on where a function is defined, but on how it is called.
Basic Example
let obj = {
name: "Kush",
displayName() {
console.log(`My name is ${this.name}`);
}
};
obj.displayName(); // My name is KushIf the method is detached from its object, the binding changes:
let person = obj.displayName;
person(); // My name is undefinedIn non‑strict mode, this defaults to the global window object (in browsers).
In strict mode, this is undefined.
Arrow Functions
Arrow functions do not have their own this; they capture it lexically from the surrounding scope.
let obj = {
name: "Kush",
personName: () => {
console.log(`My name is ${this.name}`);
}
};
obj.personName(); // My name is undefinedUnderstanding this with Rules
JavaScript follows four main binding rules. The rule that applies depends on how a function is called.
1. Default Binding
When a regular function is called without an explicit object, this follows the default binding rule.
function show() {
console.log(this);
}
show(); // In browsers (non‑strict): Window object
// In strict mode: undefined2. Implicit Binding
When a function is called as a method of an object, this refers to that object.
const user = {
name: "Kush",
greet() {
console.log(this.name);
}
};
user.greet(); // KushLosing Implicit Binding
A common mistake is to lose the object reference:
const user = {
name: "Kush",
greet() {
console.log(this.name);
}
};
const greetFn = user.greet;
greetFn(); // undefined (default binding applies)3. Explicit Binding (call, apply, bind)
You can explicitly set this using call, apply, or bind.
const user1 = { name: "Kush" };
const user2 = { name: "Rahul" };
function greet() {
console.log(this.name);
}
greet.call(user1); // Kush
greet.call(user2); // Rahul4. Arrow Function (Lexical Binding)
Arrow functions inherit this from their lexical (surrounding) scope.
const user = {
name: "Kush",
greet: () => {
console.log(this.name);
}
};
user.greet(); // undefined (inherits from global scope)Correct Use of Arrow Functions
Arrow functions are useful inside another method, where they capture the method’s this.
const user = {
name: "Kush",
greet() {
const say = () => {
console.log(this.name);
};
say();
}
};
user.greet(); // KushCommon Asynchronous Example (setTimeout)
Problem: Regular Function Callback
const user = {
name: "Kush",
greet() {
setTimeout(function () {
console.log(this.name);
}, 1000);
}
};
user.greet(); // undefined (callback's `this` is global)Fix: Arrow Function Callback
const user = {
name: "Kush",
greet() {
setTimeout(() => {
console.log(this.name);
}, 1000);
}
};
user.greet(); // KushQuiz: Predict the Output
const user = { name: "Kush", greet() { setTimeout(function () { console.log(this.name); }, 0); } }; user.greet();const user = { name: "Kush", greet() { setTimeout(() => { console.log(this.name); }, 0); } }; user.greet();const user1 = { name: "Kush" }; const user2 = { name: "Rahul" }; function greet() { console.log(this.name); } greet.call(user1); greet.call(user2);const user = { name: "Kush" }; const greet = () => { console.log(this.name); }; greet.call(user);const user = { name: "Kush", address: { name: "Delhi", greet() { console.log(this.name); } } }; user.address.greet();const user1 = { name: "Kush", greet() { console.log(this.name); } }; const user2 = { name: "Rahul" }; user2.greet = user1.greet; user2.greet();const user = { name: "Kush", greet() { return function () { console.log(this.name); }; } }; user.greet()();
If you can correctly predict all the outputs, you’re on the right track!