Understanding `this` in JavaScript: Arrow Functions vs Function Keyword


If you’ve been writing JavaScript for a while, chances are you’ve run into one of the most confusing keywords: this
. Sometimes it gives you what you expect, sometimes it doesn’t — and suddenly your console.log
shows undefined
.
Let’s clear up the confusion with a practical example.
Example 1: Using an Arrow Function
const user = {
name: "Virat",
greet: function () {
setTimeout(() => {
console.log(`${this.name}`);
});
},
};
user.greet(); // Output: "Virat"
✅ Here, the output is "Virat".
Why?
Arrow functions don’t have their own
this
.Instead, they inherit it from the surrounding scope (lexical scoping).
In this case, the surrounding scope is the
greet
method, and insidegreet
,this
refers to theuser
object.
So this.name
→ "Virat"
.
Example 2: Using a Regular Function
const user1 = {
name: "Chetana",
greet: function () {
setTimeout(function () {
console.log(`${this.name}`);
});
},
};
user1.greet(); // Output: undefined
❌ Here, the output is undefined
.
Why?
Regular functions create their own
this
at runtime.In the
setTimeout
callback,this
doesn’t point touser1
.Instead, it defaults to the global object (
window
in browsers,global
in Node.js).Since the global object doesn’t have a
name
property, we getundefined
.
Story Analogy: Arrow vs Regular Functions
Imagine you’re in a restaurant.
A regular function is like a new waiter who introduces themselves and forgets who you are. When they take your order, they don’t remember which table you’re sitting at.
An arrow function is like a waiter’s assistant who doesn’t introduce themselves. They simply shadow the main waiter and remember exactly which table (context) the main waiter is serving.
That’s the difference in how this
is handled!
Fixing the Regular Function Example
If you still want to use the function
keyword, you have a couple of options:
Option 1: Save this
in a variable
const user1 = {
name: "Chetana",
greet: function () {
const self = this; // capture this
setTimeout(function () {
console.log(self.name);
});
},
};
user1.greet(); // "Chetana"
Option 2: Use .bind(this)
const user1 = {
name: "Chetana",
greet: function () {
setTimeout(function () {
console.log(this.name);
}.bind(this));
},
};
user1.greet(); // "Chetana"
Key Differences Between Arrow Functions and Regular Functions
this
bindingArrow → inherits from parent scope.
Regular → depends on how the function is called.
Constructors
Arrow → ❌ can’t be used as constructors.
Regular → ✅ can act as constructors with
new
.
Arguments object
Arrow → ❌ no own
arguments
object.Regular → ✅ has its own
arguments
.
Takeaway
Use arrow functions when you want to preserve the outer
this
(e.g., callbacks, async code).Use regular functions when you need your own
this
(e.g., object methods, constructors).
Mastering the difference saves hours of debugging weird undefined
logs and makes your code much more predictable.
Subscribe to my newsletter
Read articles from Virat Srivastava directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
