Understanding "this" and Closures in JavaScript: A Deep Dive with Arrow vs Regular Functions


When diving deeper into JavaScript, especially when dealing with nested functions and object methods, developers often encounter unexpected behavior with the this
keyword. Add arrow functions to the mix, and it becomes a real puzzle. One of the elegant ways to solve this confusion is by using closure variables. In this article, we’ll explore how this
behaves in different contexts and how closures help us navigate these tricky situations.
What Is ‘this‘ in JavaScript?
In an object method, this
refers to the object that is calling the method.
const user = {
name: "Yunus",
greet() {
console.log(`Hello, my name is ${this.name}`);
}
};
user.greet(); // "Hello, my name is Yunus"
Here, this.name
inside greet()
refers to user.name
, which is "Younus"
. Because user
is calling greet()
. It’s a reference to the object that is executing the current function.
In regular functions,
this
is dynamic and refers to the caller of the function.In arrow functions,
this
is lexically bound, it doesn't refer to the caller but rather to the context in which the function was defined.It depends on how the function is called, not where it’s written.
Example Scenario: Nested Objects and Mixed Functions
const students = {
gender: ["Male", "Female", "Others"],
school: ["Abc Model School", "Cba Model School"],
studentOne: function () {
const details = {
fistName: "Habib",
lastName: "Munshi",
fullName: function () {
return this.fistName + " " + this.lastName;
},
genderType: this.gender[0],
bioWithRegFunc: function () {
return `This is ${this.fullName()}. He is a ${
this.genderType
} student. His school name is ${this.school[0]}`;
},
bioWithArrowFunc: () => {
return `This is ${this.fullName()}. He is a ${
this.genderType
} student. His school name is ${this.school[0]}`;
},
};
return details;
},
};
let a = students.studentOne();
console.log("students", a.bioWithArrowFunc(), a.bioWithRegFunc());
Problems in This Code:
bioWithRegFunc
works well with properties insidedetails
, but can’t access theschool
array fromstudents
.bioWithArrowFunc
fails because arrow functions don’t have their ownthis
, sothis.fullName()
andthis.genderType
areundefined
.
Solution: Use Closure Variables
To bridge the gap between inner and outer scopes, we can use a closure
, by capturing the outer this
using a variable like outerThis
.
Quick Recap: What’s a Closure?
A closure is formed when a function “remembers” variables from its outer scope even after the outer function has finished executing.
Here’s the fixed version:
const students = {
gender: ["Male", "Female", "Others"],
school: ["Abc Model School", "Cba Model School"],
studentOne: function () {
const outerThis = this; // capture outer context
const details = {
fistName: "Habib",
lastName: "Munshi",
fullName: function () {
return this.fistName + " " + this.lastName;
},
genderType: outerThis.gender[0],
bioWithRegFunc: function () {
// 'this' refers to 'details'
return `This is ${this.fullName()}. He is a ${
this.genderType
} student, His school name is ${outerThis.school[0]} }`;
},
bioWithArrowFunc: () => {
// 'this' is 'studentOne' scope, so using closure variables instead
return `This is ${details.fullName()}. He is a ${
details.genderType
} student, His school name is ${outerThis.school[0]}`;
},
};
return details;
},
};
let a = students.studentOne();
console.log("students", a.bioWithArrowFunc(), a.bioWithRegFunc());
Let’s break down the code:
When studentOne()
runs:
- A new scope is created.
Inside this scope:
const outerThis = this;
stores a reference to thestudents
object (becausethis
insidestudentOne
refers tostudents
).const details = { ... }
creates an object.Even after
studentOne()
finishes, the inner functions (likebioWithArrowFunc
) rememberouterThis
anddetails
because of JavaScript closures.
bioWithRegFunc
:
Regular function, so
this
refers todetails
.We access outer values like
school
throughouterThis
.
bioWithArrowFunc
:
- Arrow function can’t use
this
to accessdetails
— but we can use thedetails
object directly because it’s in the closure scope.
Why Use Closures Here?
Arrow functions don’t get their own
this
, so we can’t rely onthis
in them.But closures let us access variables from the outer function.
That’s why we use
outerThis
or just directly refer todetails
— they’re remembered.
Final Words:
Understanding how this
behaves in different function types is crucial in JavaScript. By combining this knowledge with closures, we can write more predictable and bug-free code—especially when working with nested scopes or callbacks.
Subscribe to my newsletter
Read articles from Md. Monirul Islam directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by

Md. Monirul Islam
Md. Monirul Islam
Passionate and detail-oriented React Developer with over 5 years of industry experience in building scalable web and mobile applications using modern technologies such as React.js, Next.js, TypeScript, and Node.js. Proven track record of delivering high-quality solutions in the fintech, real estate, and government sectors.