Interview question
How does the 'this' keyword behave differently in prototype methods vs arrow functions defined as class fields? Prototype methods vs class fields के रूप में arrow functions में 'this' कैसे अलग व्यवहार करता है?
Answer
Regular prototype methods have a dynamic 'this' that depends on how they're called, while arrow functions defined as class fields lexically bind 'this' to the instance at creation time.
class Counter {
count = 0;
// Regular method - added to Counter.prototype
// 'this' depends on HOW it's called
incrementRegular() {
this.count++;
}
// Arrow function class field - 'this' is bound lexically to the instance
// Created fresh for EACH instance (not shared on the prototype)
incrementArrow = () => {
this.count++;
};
}
const counter = new Counter();
// Calling directly - both work fine
counter.incrementRegular(); // this.count = 1, works
counter.incrementArrow(); // this.count = 2, works
// Problem case: passing method as a callback, losing the 'this' binding
const regularRef = counter.incrementRegular;
// regularRef(); // TypeError: Cannot read properties of undefined - 'this' is lost
const arrowRef = counter.incrementArrow;
arrowRef(); // works fine! 'this' remains bound to counter
// Common real-world scenario: event handlers or setTimeout
setTimeout(counter.incrementRegular, 100); // BROKEN - 'this' is undefined/global
setTimeout(counter.incrementArrow, 100); // WORKS - 'this' stays bound to counter
// The trade-off: arrow function fields create a NEW function per instance
// (memory cost), while regular methods are shared once on the prototype
console.log(Counter.prototype.incrementRegular); // exists on prototype
console.log(Counter.prototype.incrementArrow); // undefined - it's an instance property, not on prototypeRegular prototype methods में dynamic 'this' होता है जो call होने के तरीके पर depend करता है, जबकि class fields के रूप में arrow functions 'this' को instance creation के समय lexically bind कर देते हैं।
class Counter {
count = 0;
// Regular method - Counter.prototype पर
incrementRegular() {
this.count++;
}
// Arrow function class field - हर instance के लिए fresh
incrementArrow = () => {
this.count++;
};
}
const counter = new Counter();
counter.incrementRegular(); // ठीक काम करता है
counter.incrementArrow(); // ठीक काम करता है
// Problem: method को callback की तरह pass करना, 'this' खो जाता है
const regularRef = counter.incrementRegular;
// regularRef(); // TypeError - 'this' खो गया
const arrowRef = counter.incrementArrow;
arrowRef(); // काम करता है! 'this' अभी भी bound है
// Real-world scenario: setTimeout
setTimeout(counter.incrementRegular, 100); // TOOTA - 'this' undefined
setTimeout(counter.incrementArrow, 100); // काम करता है
// Trade-off: arrow function fields हर instance में नया function बनाते हैं
console.log(Counter.prototype.incrementRegular); // prototype पर मौजूद
console.log(Counter.prototype.incrementArrow); // undefinedWas this answer clear?