You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

TypeScript方法与事件处理器兼容问题:点击输出异常

Why does clicking the button log undefined instead of two 1s?

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 one undefined appears (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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.25 07:07:44