addEventListener 与 attachEvent 的区别
对比两种事件监听方法的语法、兼容性和行为差异
问题
addEventListener() 和 attachEvent() 有什么区别?如何编写兼容的事件绑定函数?
解答
基本语法对比
// addEventListener - W3C 标准方法
element.addEventListener('click', handler, false);
// attachEvent - IE8 及以下专有方法(已废弃)
element.attachEvent('onclick', handler);
主要区别
| 特性 | addEventListener | attachEvent |
|---|---|---|
| 标准 | W3C 标准 | IE 专有 |
| 事件名 | 不带 on 前缀 | 需要 on 前缀 |
| this 指向 | 绑定的元素 | window |
| 事件流 | 支持捕获和冒泡 | 只支持冒泡 |
| 执行顺序 | 按添加顺序 | 顺序不确定 |
代码示例
const btn = document.getElementById('btn');
// addEventListener 中 this 指向元素
btn.addEventListener('click', function(e) {
console.log(this); // <button id="btn">
console.log(e.target); // <button id="btn">
console.log(e.type); // 'click'
}, false);
// attachEvent 中 this 指向 window(IE8 及以下)
// btn.attachEvent('onclick', function(e) {
// console.log(this); // window
// console.log(e.srcElement); // IE 用 srcElement 代替 target
// });
兼容性封装
// 添加事件
function addEvent(element, type, handler) {
if (element.addEventListener) {
// 标准方法
element.addEventListener(type, handler, false);
} else if (element.attachEvent) {
// IE8 及以下
element.attachEvent('on' + type, handler);
} else {
// 降级处理
element['on' + type] = handler;
}
}
// 移除事件
function removeEvent(element, type, handler) {
if (element.removeEventListener) {
element.removeEventListener(type, handler, false);
} else if (element.detachEvent) {
element.detachEvent('on' + type, handler);
} else {
element['on' + type] = null;
}
}
// 使用示例
const btn = document.getElementById('btn');
function handleClick(e) {
// 兼容获取事件对象
e = e || window.event;
// 兼容获取目标元素
const target = e.target || e.srcElement;
console.log('clicked:', target);
}
addEvent(btn, 'click', handleClick);
修正 attachEvent 的 this 指向
function addEventFixed(element, type, handler) {
if (element.addEventListener) {
element.addEventListener(type, handler, false);
} else if (element.attachEvent) {
// 用 call 修正 this 指向
element.attachEvent('on' + type, function(e) {
handler.call(element, e || window.event);
});
}
}
关键点
addEventListener是标准方法,attachEvent是 IE8 及以下专有方法,现已废弃- 事件名不同:
clickvsonclick addEventListener的 this 指向元素,attachEvent的 this 指向 windowaddEventListener第三个参数控制捕获/冒泡,attachEvent只支持冒泡- 现代开发无需考虑
attachEvent,IE8 已被淘汰
目录