tezvyn:

Why does this lose context in class callbacks and two TypeScript fixes?

AI-drafted, machine-checkedSource: developer.mozilla.orgintermediate
Why does this lose context in class callbacks and two TypeScript fixes?

This tests runtime this binding. Explain that regular functions get this from the call site, so passing a method strips its object context. Fix with an arrow property or constructor bind. Red flag: var self = this or claiming TypeScript changes binding.

WHAT THIS TESTS: This question tests whether you understand that the value of this in JavaScript and TypeScript is determined by how a function is invoked, not how it is written. It specifically checks if you know that regular functions use runtime binding, which means detaching a method from its object and passing it as a callback causes this to become undefined in strict mode or the global object otherwise. It also checks your fluency with TypeScript class syntax and modern fixes that preserve context without resorting to legacy patterns.

A GOOD ANSWER COVERS: First, explain the mechanism: when you write element.addEventListener('click', myInstance.handleClick), you are passing a reference to the function only, severing its connection to myInstance. At call time, the browser invokes it as a standalone function, so this no longer points to the class instance. Second, present two distinct fixes. Fix one is an arrow function property: handleClick = () => { ... } defined as a class field. Arrow functions inherit this from the surrounding scope at definition time, so the instance is permanently captured. Fix two is explicit binding in the constructor: this.handleClick = this.handleClick.bind(this); this creates a new bound function that ignores future call-site context. Both are valid, but the arrow property is more concise.

COMMON WRONG ANSWERS: A major red flag is suggesting var self = this as a TypeScript solution; that is an obsolete ES5 workaround and signals weak modern language knowledge. Another red flag is claiming that TypeScript changes how this works; TypeScript compiles to JavaScript and leaves binding semantics entirely intact. Also avoid saying that bind, call, or apply can fix an arrow function, because arrow functions do not have their own this binding and cannot be rebound.

LIKELY FOLLOW-UPS: An interviewer might ask which fix you prefer and why. The arrow property is cleaner but creates a new function per instance, slightly increasing memory use compared to a prototype method. They might also ask how this behaves in subclassing scenarios, or how to type the event parameter correctly in TypeScript when using addEventListener with a bound method.

ONE CONCRETE EXAMPLE: Imagine a Button class with a method onClick that reads this.label. If you register it with buttonElement.addEventListener('click', button.onClick), clicking throws an error because this is undefined. To fix it, define onClick as an arrow function property: onClick = (event: MouseEvent) => { console.log(this.label); }. Alternatively, in the constructor write this.onClick = this.onClick.bind(this); and keep the method as a regular prototype method. Both ensure this refers to the Button instance when the DOM event fires.

Source: developer.mozilla.org

Read the original → developer.mozilla.org

Get five bites like this every day.

Tezvyn delivers a daily feed of 60-second tech bites with quizzes to lock in what you learn.