DEV Community

Cover image for The Real Reason Behind Arrow Functions in JavaScript
Prajwal Gaonkar
Prajwal Gaonkar

Posted on

The Real Reason Behind Arrow Functions in JavaScript

The Real Difference Between Normal Functions and Arrow Functions (Node.js)

I’ve watched a lot of explanations about arrow functions on YouTube, and almost all of them say the same thing: “they’re just shorter functions.”

That explanation feels incomplete, and honestly, a bit misleading.

The problem is, it focuses only on syntax and ignores what actually changes under the hood. In JavaScript, functions are not just reusable code blocks—they also define an execution context, and a big part of that context is this.

With normal functions, this is dynamic. It is not fixed when you write the function. Instead, it is decided later, at the moment the function is called. That means the same function can behave differently depending on how it is invoked.

Arrow functions change this behavior completely. They do not create their own this at all. Instead, they capture this from the surrounding scope at the time they are created, and that value never changes.

So the real difference is not about shorter syntax. It is about how this is handled at a fundamental level:

  • Normal functions decide this at call time (dynamic binding)
  • Arrow functions fix this at creation time (lexical binding)

This is the part most explanations skip, but it is the reason arrow functions were introduced in the first place.


The Core Difference

Normal functions and arrow functions differ in how this is determined.

Normal Function

  • Has its own this
  • this is decided at call time
  • Depends on who calls the function

Arrow Function

  • Does not have its own this
  • this is taken from the surrounding scope
  • Fixed at creation time

Example in Node.js

Normal Function

const user = {
  name: "Alice",
  greet() {
    setTimeout(function () {
      console.log(this);
    }, 1000);
  }
};

user.greet();
Enter fullscreen mode Exit fullscreen mode

Output

Timeout {
  _idleTimeout: 1000,
  ...
}
Enter fullscreen mode Exit fullscreen mode

Explanation:

  • The function inside setTimeout is called by Node
  • So this becomes a Timeout object

Arrow Function

const user = {
  name: "Alice",
  greet() {
    setTimeout(() => {
      console.log(this);
    }, 1000);
  }
};

user.greet();
Enter fullscreen mode Exit fullscreen mode

Output

{ name: 'Alice', greet: [Function: greet] }
Enter fullscreen mode Exit fullscreen mode

Explanation:

  • Arrow function does not create its own this
  • It uses this from greet, which is user

Side-by-Side Summary

Feature Normal Function Arrow Function
Own this Yes No
this decided Call time Creation time
this depends on Caller Surrounding scope

Final Mental Model

Normal function:
"I will decide this when I am called"

Arrow function:
"I will use this from where I was created"

Top comments (0)