Arrow Functions
Lexical this and Shorter Syntax
LinkedIn Hook
You're writing a React component. Inside
setInterval, you typefunction() { this.count++ }— and suddenlythisisundefined.You switch to an arrow function:
() => { this.count++ }— and it just works.Magic? No. Arrow functions don't have their own
this. They borrow it from the enclosing lexical scope, permanently, at the moment they're defined.But that same feature becomes a bug the second you use an arrow as an object method, a prototype method, or an event handler where you need
thisto be the element.In this lesson you'll learn all four "no own" rules of arrow functions — no
this, noarguments, noprototype, nonew— and exactly when a regular function is the right answer.If you've ever fixed a bug by turning
=>intofunction(or vice versa) without really knowing why — this lesson fixes that forever.Read the full lesson -> [link]
#JavaScript #InterviewPrep #ES6 #ArrowFunctions #This #Frontend #CodingInterview
What You'll Learn
- All the syntax variations — implicit return, single-param shortcut, returning object literals
- Why arrow functions have lexical
this(and noarguments, noprototype, nonew) - The four classic "do not use arrow" situations: methods, constructors, prototypes, dynamic event handlers
Why Arrows Are More Than Shorter Syntax
Arrow functions are the most visible ES6 change, but their real significance isn't the shorter syntax — it's how they handle this. Think of an arrow function as a camera that permanently records the scene it was created in. No matter where you play the recording later, the scene never changes.
Syntax Variations
// Full body
const add = (a, b) => {
return a + b;
};
// Implicit return (single expression)
const add2 = (a, b) => a + b;
// Single parameter — parentheses optional
const double = x => x * 2;
// No parameters — parentheses required
const greet = () => "Hello!";
// Returning an object — wrap in parentheses
const makeUser = (name, age) => ({ name, age });
// With array methods
const evens = [1, 2, 3, 4, 5].filter(n => n % 2 === 0);
const doubled = [1, 2, 3].map(n => n * 2);
No Own this — Lexical this
Arrow functions don't have their own this. They capture this from the enclosing lexical scope at the time they're defined.
function Timer() {
this.seconds = 0;
// Arrow function captures 'this' from Timer
setInterval(() => {
this.seconds++;
console.log(this.seconds);
}, 1000);
}
const t = new Timer(); // Works! 'this' refers to the Timer instance
// Compare with regular function (broken)
function BrokenTimer() {
this.seconds = 0;
setInterval(function() {
this.seconds++; // 'this' is window/undefined, NOT BrokenTimer
console.log(this.seconds); // NaN
}, 1000);
}
No Own arguments Object
function outer() {
// Arrow inherits 'arguments' from outer
const inner = () => {
console.log(arguments); // outer's arguments: [1, 2, 3]
};
inner();
}
outer(1, 2, 3);
// Use rest parameters instead
const sum = (...args) => args.reduce((a, b) => a + b, 0);
sum(1, 2, 3); // 6
When NOT to Use Arrow Functions
// 1. Object methods — arrow captures wrong 'this'
const person = {
name: "Rakibul",
greet: () => {
console.log(this.name); // undefined — 'this' is global, not person
}
};
// Fix: use shorthand method
const personFixed = {
name: "Rakibul",
greet() {
console.log(this.name); // "Rakibul"
}
};
// 2. Constructors — arrow functions can't be used with 'new'
const Foo = () => {};
// new Foo(); // TypeError: Foo is not a constructor
// 3. Dynamic this (event handlers)
button.addEventListener("click", () => {
console.log(this); // window, NOT the button
});
button.addEventListener("click", function() {
console.log(this); // the button element
});
// 4. Prototype methods
function Person(name) {
this.name = name;
}
Person.prototype.greet = () => {
console.log(this.name); // undefined
};
// Fix: use regular function
Person.prototype.greet = function() {
console.log(this.name);
};
Common Mistakes
- Writing object methods as arrow functions and wondering why
thisisundefinedorwindow— the arrow captured the module/globalthis, not the object. Use the shorthand method syntaxgreet() { ... }for methods. - Using an arrow function as a constructor —
new Foo()throws aTypeErrorbecause arrows have no[[Construct]]internal slot and noprototypeproperty. - Thinking
.call(...)or.bind(...)can "rebind" an arrow'sthis. It can't. The arguments go through, but thethispassed in is silently ignored — arrows are permanently glued to their lexical scope.
Interview Questions
Q: What are the key differences between arrow functions and regular functions?
Arrow functions: (1) no own
this— use lexicalthis, (2) noargumentsobject, (3) can't be used as constructors withnew, (4) noprototypeproperty, (5) can't be used as generators. Use rest params (...args) instead ofarguments.
Q: When should you NOT use arrow functions?
Don't use them as: object methods (wrong
this), constructors (throws error), prototype methods (wrongthis), event handlers where you needthisto be the element, and functions that need their ownargumentsobject.
Q: Can you use call, apply, or bind on arrow functions?
You can call them, but they have no effect on
this. Arrow functions always use thethisfrom their enclosing scope, regardless of how they're invoked. The methods still work for passing arguments, though.
Q: Can arrow functions be used as constructors?
No.
new Foo()whereFoois an arrow throwsTypeError: Foo is not a constructor. Arrows have no[[Construct]]slot and noprototypeproperty, so they can never produce a new instance.
Quick Reference — Cheat Sheet
ARROW FUNCTIONS — QUICK MAP
Syntax:
(a, b) => a + b -> implicit return
x => x * 2 -> single param, no parens
() => "hi" -> no params, parens required
() => ({ key: val }) -> return object literal (wrap!)
(a, b) => { return a + b; } -> block body, explicit return
No own (inherited from lexical parent):
- this
- arguments
- super
- new.target
Not usable as:
- constructor (no `new`)
- generator (no `function*` arrow)
- dynamic-this method
Prefer arrows for:
- array callbacks (map/filter/reduce)
- setTimeout/setInterval in classes
- promise .then chains
- short pure-expression helpers
Previous: Template Literals -> Backticks and Tagged Templates Next: Default Parameters -> Clean Defaults Without Falsy Traps
This is Lesson 9.2 of the JavaScript Interview Prep Course — 14 chapters, 87 lessons.