Arrow vs Regular Functions: Every Single Difference
Arrow ka apna this nahi hota — yehi uski superpower hai aur yehi uski kamzori.
Arrow functions appeared in ES6 as a compact syntax. But the differences go way beyond just "less typing" — they fundamentally change how this, arguments, and construction work.
// Implicit return — concise
const double = x => x * 2;
const add = (a, b) => a + b;
const getObj = () => (({ name: 'Sai' })); // parens for object literal
// Regular function — explicit
function doubleRegular(x) {
return x * 2;
}
// Returning object literal — common trap!
// const wrong = () => { name: 'Sai' }; // Returns undefined!
// 'name:' is a label, not a property key
// const right = () => ({ name: 'Sai' }); // Wrapping in () fixes it
// Arrow CANNOT be a generator
// function* gen() { yield 1; } // OK
// const genArrow = *() => { yield 1; }; // SyntaxError!
{ is parsed as a block statement, not an object literal. () => { name: 'Sai' } returns undefined — name: is a label, not a property. Wrap in parentheses: () => ({ name: 'Sai' }) forces expression evaluation.Key syntax rules:
• Single parameter: no parentheses needed — x => x * 2
• Zero or multiple parameters: parentheses required — () => 42, (a, b) => a + b
• Arrow functions are always expressions — they cannot be hoisted like function declarations
• Arrow functions are always anonymous (though .name can be inferred from the variable)
Arrow functions do NOT have their own this binding. This is the single most important difference — and the one that trips up the most developers.
Inside an arrow function, this is inherited from the enclosing Lexical Environment. It's captured at definition time, not resolved at call time.
function Timer() {
this.seconds = 0;
// Regular function — 'this' is lost in setInterval
// setInterval(function() { this.seconds++; }, 1000); // NaN or error!
// Arrow function — 'this' inherited from Timer scope
setInterval(() => {
this.seconds++; // 'this' is the Timer instance!
}, 1000);
}
const timer = new Timer();
setTimeout(() => console.log(timer.seconds), 2500); // 2
// .call() cannot override arrow's this
const arrow = () => this;
console.log(arrow.call({ x: 1 })); // window/undefined, NOT { x: 1 }
MustLoadThis reads the receiver from the call site. For arrow functions, V8 replaces this with a direct context slot access — exactly like accessing a closed-over variable. There is no runtime this-resolution at all. The this value is baked into the arrow's closure at creation time.Arrow functions are missing several features that regular functions have. These aren't bugs — they're intentional design decisions.
No arguments object: Arrow functions don't have their own arguments binding. If you reference arguments inside an arrow, it looks up the scope chain to find the nearest enclosing function's arguments — or throws a ReferenceError.
// No 'arguments' object
const regular = function() {
console.log(arguments[0]); // Works
};
regular('Hello'); // 'Hello'
const arrow = () => {
// console.log(arguments[0]); // ReferenceError or outer arguments!
};
arrow('Hello');
// Correct way for arrows: Rest parameters
const arrowRest = (...args) => {
console.log(args[0]); // 'Hello'
};
arrowRest('Hello');
Cannot use new: Arrow functions have no [[Construct]] internal method and no .prototype property.
const F = () => {};
// new F(); // TypeError: F is not a constructor
function G() {}
new G(); // OK
console.log(G.prototype); // {}
console.log(F.prototype); // undefined
new.Knowing when to use arrows vs regular functions is more important than knowing the syntax. Here are the practical rules:
✅ USE arrows for: Short callbacks (map, filter, reduce), preserving this in nested functions, one-liner expressions.
❌ DO NOT use arrows for: Object methods, Prototype methods, Event handlers that need this = element, Functions that need arguments, Constructors.
// ❌ BAD: Arrow as object method
const user = {
name: 'Sai',
greet: () => 'Hello, ' + this.name // 'this' is window/undefined!
};
console.log(user.greet()); // 'Hello, undefined'
// ✅ GOOD: Shorthand method (regular function)
const userGood = {
name: 'Sai',
greet() { return 'Hello, ' + this.name; } // 'this' is userGood
};
console.log(userGood.greet()); // 'Hello, Sai'
// ❌ BAD: Arrow as event handler needing 'this'
const button = document.createElement('button');
// button.addEventListener('click', () => {
// this.classList.toggle('active'); // 'this' is NOT the button!
// });
// ✅ GOOD: Regular function for event 'this'
// button.addEventListener('click', function() {
// this.classList.toggle('active'); // 'this' IS the button
// });
handleClick = () => { ... } is popular in React to auto-bind this. But every instance gets its OWN copy of the arrow function, instead of sharing one on the prototype. For a component with 1000 instances, that's 1000 extra function objects in memory.Here's the complete comparison — memorize this for interviews:
Feature Arrow Regular
─────────────────────────────────────────────
this binding Lexical Dynamic
arguments object No Yes
new keyword No Yes
.prototype property No Yes
yield (generator) No Yes
super Enclosing Method only
Duplicate params No (strict) Yes (sloppy)
Hoisting No (expr) Yes (decl)
Constructor No Yes
Rule of thumb: If you need this, arguments, or new — use a regular function. Otherwise, arrow is fine.
// Arrow is perfect for pure callbacks
const numbers = [1, 2, 3, 4];
const doubled = numbers.map(n => n * 2); // Clean, no 'this' needed
// Regular is needed for methods
const calculator = {
value: 0,
add(n) { this.value += n; return this; }, // Needs 'this'
double() { return this.value * 2; }
};Lo kar liya — Key Points:
- ✅ Arrow functions do not have their own
this— they inherit it from the enclosing lexical scope - ✅
.call(),.apply(), and.bind()cannot change thethisof an arrow function - ✅ Arrow functions have no
argumentsobject — use rest parameters(...args)instead - ✅ Arrow functions cannot be used as constructors (no
new, no.prototype) - ✅ Never use arrows for object methods or event handlers that need
thisto be the receiver - ✅ V8 implements arrow
thisas a context slot access (like a closed-over variable), not dynamic lookup
Want to track your progress?
Log in to save your place and pick up where you left off.
Progress track karna chahte ho?
Login karo apni progress save karne ke liye aur jahan chhoda tha wahan se shuru karo.
Login