Class Method Binding
Class methods lose their this value when detached from the instance, so callbacks need binding or an arrow wrapper.
this is bound at the call site. Pulling a method off an instance and calling it as a plain function loses the instance.
Classes always run in strict mode, so a detached method receives undefined as this. The same problem appears when a method is passed as a callback.
class Counter {
constructor() {
this.count = 0;
}
increment() {
this.count += 1;
}
}
const c = new Counter();
c.increment();
console.log(c.count); // 1
const inc = c.increment;
inc(); // TypeError, this is undefined
setTimeout(c.increment, 100); // also loses thisBinding in the constructor works everywhere. A class-field arrow is the modern default because the arrow captures this when the instance is created. Wrapping at the call site is useful when you do not control the class.
class Counter1 {
constructor() {
this.count = 0;
this.increment = this.increment.bind(this);
}
increment() { this.count += 1; }
}
class Counter2 {
count = 0;
increment = () => { this.count += 1; };
}
const c1 = new Counter1();
setTimeout(c1.increment, 100);
const c2 = new Counter2();
setTimeout(c2.increment, 100);In production
The class-field arrow (increment = () => { ... }) prevents accidental callback bugs at every call site. Use .bind(this) in the constructor for environments that avoid class fields.