事件流中this指向取决于绑定方式:onclick和addeventlistener中this指向目标元素,attachevent指向window,箭头函数继承外层作用域;事件委托应使用e.target而非this获取触发元素。

在事件流中,this 的指向看似固定,实则高度依赖绑定方式和调用上下文。当事件在捕获→目标→冒泡三阶段中传播,又混用不同绑定语法(如 onclick、addEventListener、箭头函数、attachEvent),this 就容易“失联”——不是指向预期的 DOM 元素,而是变成 window、undefined,甚至外层作用域对象。
明确每种绑定方式下 this 的归属
不同注册方式决定了 this 的默认宿主,不能靠经验猜测:
-
elem.onclick = handler→ this 指向elem(DOM 元素本身) -
elem.addEventListener('click', handler, false)→ this 指向elem(目标元素) -
elem.addEventListener('click', handler, true)→ this 仍指向elem(捕获阶段不改变 this 绑定逻辑) -
elem.attachEvent('onclick', handler)(IE8-)→ this 指向window,需手动修正:handler.call(elem) - 箭头函数作为事件处理器 → this 继承外层词法作用域,永远不指向 DOM 元素,慎用于需要操作
this的场景
避免 this 在事件委托中意外漂移
事件委托依赖冒泡,但委托处理器里的 this 指向的是绑定事件的父元素,而非真正被点击的子元素。若误把 this 当作点击目标,就会出错:
- 正确做法:用
e.target获取实际触发事件的元素,e.currentTarget才等价于传统this - 示例:
list.addEventListener('click', e => { console.log(e.target); console.log(e.currentTarget); })—— 点击列表项时,e.target是<li>,e.currentTarget是<ul></ul> - 不要写
this.querySelector('.delete')期望删当前项;应写e.target.closest('li').remove()
统一 this 行为的实用策略
不依赖隐式绑定,主动控制更可靠:
- 显式绑定:用
.bind(elem)或handle.bind(elem)固定 this - 闭包传参:把元素作为参数传入,避开 this 问题,例如
elem.addEventListener('click', () => handleClick(elem)) - 封装兼容函数:对老 IE 做
call修正,现代浏览器保持原生行为 - 禁用箭头函数处理 DOM 操作:除非你明确不需要访问触发元素,否则改用普通函数
调试时快速定位 this 来源
遇到 this 不对,别猜,直接查:
- 在事件处理器开头加
console.log({ this, e: { target: e.target, currentTarget: e.currentTarget } }) - 在 Chrome DevTools 的 Elements 面板选中元素 → Event Listeners 标签 → 查看每个监听器的绑定方式(inline / addEventListener / attachEvent)
- 检查是否用了 jQuery 或其他库封装,它们可能重写了 this(如 jQuery 的
$(...).on(...)中 this 默认是 DOM 元素,但内部机制已封装)











