TypeScript方法与事件处理器兼容问题:点击输出异常
Let's start by looking at your code, then break down what's going wrong and how to fix it.
Your Code
TypeScript Script
class foo { v: number = 1; public bar() { console.log(this.v); } } var a = new foo(); var b = new foo(); document.getElementById('test').addEventListener("click", a.bar); document.getElementById('test').addEventListener("click", b.bar);
HTML
<html lang="en"> <body> <button id="test">Test</button> </body> </html>
Expected vs. Actual Behavior
Expected: Clicking the "Test" button logs two
1s to the console
Actual: Only oneundefinedappears (we'll explain why it's actually two hiding in plain sight)
What's Going Wrong?
1. The this Context is Broken
When you pass a.bar or b.bar to addEventListener, you're not passing the method attached to the a/b instance. Instead, you're passing a reference to the standalone bar function from the foo class prototype.
When the button's click event fires, the browser invokes this function with this set to the button element itself (the event target). Since the button has no v property, this.v evaluates to undefined.
2. Why Only One undefined?
You did add two event listeners—both are running! Most browser consoles automatically group identical log messages by default. If you check your console settings (look for options like "Group similar messages" or "Collapse identical logs") and disable that, you'll see two lines of undefined.
How to Fix It
We need to make sure the bar method retains its original this context (the foo instance) when called as an event handler. Here are three solid approaches:
1. Wrap the Method Call in an Arrow Function
Arrow functions inherit this from the scope they're defined in, so they'll keep the reference to your foo instance:
document.getElementById('test').addEventListener("click", () => a.bar()); document.getElementById('test').addEventListener("click", () => b.bar());
2. Explicitly Bind the Method to the Instance
Use bind() to permanently tie the bar method to the a or b instance. This creates a new function that always uses the correct this:
document.getElementById('test').addEventListener("click", a.bar.bind(a)); document.getElementById('test').addEventListener("click", b.bar.bind(b));
3. Define bar as an Arrow Function in the Class
If you define the method as an arrow function directly in the class, it will automatically bind this to the instance when the class is instantiated. This is a clean option if you know you'll always use bar in contexts where this needs to stay tied to the instance:
class foo { v: number = 1; public bar = () => { console.log(this.v); } }
内容的提问来源于stack exchange,提问作者Steve

