在 DOM 事件回调中,this 默认指向触发事件的 DOM 元素(如 addEventListener 中的普通函数),但箭头函数会继承外层 this;对象方法需 bind、闭包或类中箭头函数属性来保持实例绑定;优先用 event.target/event.currentTarget 区分事件源与监听器。

在 JavaScript 的 DOM 事件回调中,this 的指向容易出错,核心原因是事件处理器被调用时的执行上下文(context)由调用方式决定,而非定义位置。默认情况下,原生事件绑定(如 addEventListener 或 onclick)会使 this 指向触发事件的 DOM 元素——这通常是期望行为;但若回调是对象方法或箭头函数,this 就可能丢失或指向意外对象。
使用 addEventListener 时 this 默认指向事件目标元素
这是最常见也最推荐的方式。只要回调是普通函数(非箭头函数),且直接作为事件监听器传入,this 就自动绑定为当前触发事件的 DOM 元素:
const btn = document.getElementById('myBtn');
btn.addEventListener('click', function() {
console.log(this); // ? 指向 btn 元素
console.log(this.id); // 'myBtn'
});
✅ 优点:语义清晰、无需额外绑定、兼容性好。
⚠️ 注意:如果用箭头函数替代,this 将继承外层作用域(通常是 window 或 undefined),不再指向元素:
btn.addEventListener('click', () => {
console.log(this); // ❌ 不是 btn,而是外层 this(如模块顶层为 undefined)
});
在对象方法中保持 this 指向实例
当事件回调是某个对象的方法(例如 obj.handleClick)时,直接传入会导致 this 脱离对象:
const obj = {
name: 'MyComponent',
handleClick() {
console.log(this.name); // ❌ this 指向 btn,不是 obj → undefined
}
};
btn.addEventListener('click', obj.handleClick);
有三种可靠解法:
立即学习“Java免费学习笔记(深入)”;
-
显式绑定
bind:在添加监听器时固定this:btn.addEventListener('click', obj.handleClick.bind(obj)); -
使用匿名函数包裹(闭包):
btn.addEventListener('click', () => obj.handleClick());(此时this在handleClick内部仍取决于其定义方式;若handleClick是普通函数,内部this仍是obj) -
类中用箭头函数属性(ES6+ 类语法常用):
class MyComponent { constructor() { this.name = 'MyComponent'; this.btn = document.getElementById('myBtn'); this.btn.addEventListener('click', this.handleClick); } handleClick = () => { // ✅ 箭头函数自动捕获构造时的 this console.log(this.name); // 'MyComponent' }; }
需要访问事件源元素?优先用 event.target 或 event.currentTarget
即使 this 被正确绑定,有时也需要区分「谁触发了事件」和「谁绑定了监听器」:
-
event.target:实际触发事件的底层元素(可能为子元素,如按钮内的<span>) -
event.currentTarget:绑定事件监听器的元素(即this在普通函数中的值)
例如委托监听 ul,点击 li 时:
ul.addEventListener('click', function(event) {
console.log(this === event.currentTarget); // true
console.log(event.target); // 可能是 li 或其子节点
console.log(event.currentTarget); // 始终是 ul
});
避免内联 HTML 事件处理器(onclick="...")中的 this 混乱
HTML 中写 onclick="handler()" 会创建全局作用域调用,this 指向 window,且无法访问组件实例:
<button onclick="handleClick()">Click</button>
<script>
function handleClick() {
console.log(this); // ❌ window,不是 button
}
</script>
✅ 正确做法:完全放弃内联写法,统一用 addEventListener + 外部 JS 控制。


















