Arrow Functions & this - The Simple Rules
Golden Rule: Arrow functions are this-blind. They steal this from their parent scope (where they’re written, not called).
Rule 1: Arrow Functions Don’t Have Their Own this
javascript
function normalFunc() {
console.log(this); // Has its own 'this'
}
const arrowFunc = () => {
console.log(this); // Borrows 'this' from outside
};Rule 2: They Look UP the Scope Chain for this
Step-by-step process:
- Arrow function needs
this - “I don’t have
this, let me check my parent” - Goes up one level in scope
- If parent has
this, use that - If parent is also arrow function, keep going up
- Eventually finds a regular function or global scope
Common Scenarios:
Scenario 1: Arrow in Object (DOESN’T WORK)
javascript
const obj = {
name: "John",
greet: () => {
console.log(this.name); // undefined
}
};
obj.greet(); // undefinedWhy: Arrow function looks for parent scope → finds global scope → this = undefined
Scenario 2: Arrow Inside Method (WORKS)
javascript
const obj = {
name: "John",
greet() { // Regular method - has 'this = obj'
const arrow = () => {
console.log(this.name); // "John"
};
arrow();
}
};
obj.greet(); // "John"Why: Arrow function looks up → finds greet() method → steals its this = obj
Scenario 3: Nested Arrows
javascript
const obj = {
name: "John",
greet() { // this = obj
const arrow1 = () => { // steals from greet: this = obj
const arrow2 = () => { // steals from arrow1: this = obj
console.log(this.name); // "John"
};
arrow2();
};
arrow1();
}
};Step-by-Step Decision Tree:
When you see an arrow function using this:
-
Is it directly in an object? →
this = undefined/windowjavascript
const obj = { arrow: () => this }; // Global 'this' -
Is it inside a regular method? →
this = objectjavascript
const obj = { method() { // this = obj const arrow = () => this; // steals obj } }; -
Is it inside another arrow? → Keep going up until you find regular function
javascript
const obj = { method() { // this = obj const arrow1 = () => { // this = obj const arrow2 = () => this; // this = obj }; } }; -
Is it in global scope? →
this = undefined(strict) orwindowjavascript
const arrow = () => this; // Global scope
Common Interview Traps:
Trap 1: Looks like it should work
javascript
const user = {
name: "John",
greet: () => console.log(`Hi ${this.name}`) // undefined!
};Trap 2: setTimeout with arrow vs regular
javascript
const obj = {
name: "John",
test() {
// Arrow - inherits 'this' from test()
setTimeout(() => console.log(this.name), 100); // "John"
// Regular - loses 'this' in setTimeout
setTimeout(function() { console.log(this.name); }, 100); // undefined
}
};Trap 3: Event handlers
javascript
const obj = {
name: "John",
setupHandler() {
// Arrow - keeps 'this = obj'
button.onclick = () => console.log(this.name); // "John"
// Regular - 'this' becomes button element
button.onclick = function() { console.log(this.name); }; // undefined
}
};Visual Scope Chain:
javascript
// Global scope (this = undefined/window)
const obj = {
name: "John",
// Object literal (no function scope, still global)
badArrow: () => this, // Global 'this'
// Method scope (this = obj)
goodMethod() {
// Arrow inherits from method
const arrow = () => this; // obj's 'this'
function inner() {
// Regular function (this = undefined)
const arrow2 = () => this; // undefined
}
}
};The Mental Model:
Think of arrows as “transparent to this”:
- They’re like windows - you see through them to find the real
this - Keep looking up scopes until you find a regular function or global scope
- Whatever
thisthat scope has, the arrow uses
Quick Check:
- Find the arrow function
- Go up one scope level
- Is it a regular function? Use its
this - Is it another arrow? Keep going up
- Hit global scope? Use global
this
Bottom line: Arrows inherit this from their writing location, not calling location. They look up the scope chain until they find a regular function with this.
