addEventLinstener与attachEvent区别、兼容性问题
我们知道,绑定事件的方法一般是这样的:
//对象.事件 = 处理函数
//例如:
<input type="button" value="按钮" id="btn"/>
<script>
document.getElementById('btn').onclick=function () {
console.log("first");
};
</script>
那么,为什么还要通过addEventLinstener或者attachEvent方法来绑定事件呢?通过下面一个例子你就知道通过(对象.事件 = 处理函数
)绑定事件的劣势:
<input type="button" value="按钮" id="btn"/>
<script>
var btnObj = document.getElementById('btn');
btnObj.onclick=function () {
console.log("first");
};
btnObj.onclick=function () {
console.log("second");
};
btnObj.onclick=function () {
console.log("third");
};
</script>
运行的结果是这样的:
很明显,通过(对象.事件 = 处理函数)的方式,为一个对象绑定多次同一事件,那么只有最后一次绑定执行,其他都被覆盖了,所以这就是为什么通过引用addEventLinstener和attachEvent为对象绑定事件了,下面一个例子弥补了(对象.事件 = 处理函数)方式的缺陷:
//关于addEventLinstener的语法可以点击查看
<input type="button" value="按钮" id="btn"/>
<script>
var btnObj = document.getElementById('btn');
btnObj.addEventListener("click",function () {
console.log("first");
},false);
btnObj.addEventListener("click",function () {
console.log("second");
},false);
btnObj.addEventListener("click",function () {
console.log("third");
},false);
</script>
运行的结果是这样的:
在IE8及以下的版本,运行结果是这样的:
那么试下通过attachEvent的方式来绑定事件:
//attachEvent方法不属于W3C标准,它是IE独有的,所以在MDN文档查不到此方法
/**attachEvent的用法:
参数1:事件类型—事件名字,有on
参数2:事件处理函数—函数(命名函数,匿名函数)
对象.attachEvent(事件类型,处理函数)*/
<input type="button" value="按钮" id="btn"/>
<script>
var btnObj = document.getElementById('btn');
btnObj.attachEvent("onclick",function () {
console.log("first");
});
btnObj.attachEvent("onclick",function () {
console.log("second");
});
btnObj.attachEvent("onclick",function () {
console.log("third");
});
</script>
在IE5-IE10的版本运行结果:
在谷歌、火狐,包括Edge的运行结果:
那么问题来了,如何让自己的代码可以在各个浏览器运行,不担心浏览器不支持而导致出错呢?我们知道如果这个属性在浏览器中不支持,那么这个属性的类型是undefined,判断这个属性的类型 是不是undefined,就知道浏览器是否支持,我们来验证一下:
console.log(btnObj.addEventListener);
console.log(Boolean(btnObj.addEventListener));
console.log(btnObj.attachEvent);
console.log(Boolean(btnObj.attachEvent));
//在谷歌浏览器中运行结果:
根据这个特性,我们就可以写出对象绑定事件的兼容代码:
//为任意元素.绑定任意的事件, 任意的元素(对象),事件的类型,事件处理函数
function addEventListener(element,type,fn) {
//判断浏览器是否支持这个方法
if(element.addEventListener){
element.addEventListener(type,fn,false);
}else if(element.attachEvent){
element.attachEvent("on"+type,fn);
}else{
element["on"+type]=fn; //如果以上两种方法都不支持,则通过(对象.事件 = 处理函数)的方式绑定事件
}
}
解决了兼容性问题之后,我们来解决下一个问题。
相信大家都有过使用this来添加/修改属性或方法的经历,举个例子:
<input type="button" value="按钮" id="btn"/>
<script>
var btnObj = document.getElementById('btn');
btnObj.onclick = function() {
this.value = "修改";
console.log(this);
}
</script>
通过这个例子,我们可以知道:匿名函数function(){}是作为btnObj对象的方法,所以函数作为一个对象的方法,被该对象所调用,那么this指向的是该对象。
我们再来看下面的代码:
<input type="button" value="按钮" id="btn"/>
<script>
var btnObj = document.getElementById('btn');
btnObj.addEventListener('click',function(){
this.value = '修改';
console.log(this);
},false);
</script>
输出的结果是:
结果和我们想象的一样,this指向的是"btnObj"对象
那么再看下面一个例子:
<input type="button" value="按钮" id="btn"/>
<script>
var btnObj = document.getElementById('btn');
btnObj.attachEvent('onclick',function(){
this.value = '修改';
console.log(this);
});
</script>
在IE8运行输出的结果是:
按钮没有修改,所以this指向的并不是"btnObj",而是指向windows对象,attachEvent是微软公司自己定义的一个方法,addEventListener是W3C标准的方法,所以区别是显而易见的。
那么我们来总结一下:
- (对象.事件 = 处理函数):
优点 | 缺点 |
---|---|
用法简单、所有浏览器都支持 | 不能为同一对象绑定多次同一事件 |
- addEventLinstener与attachEvent区别
addEventLinstener | attachEvent |
---|---|
三个参数 | 两个参数 |
谷歌、火狐、Edge支持,IE8以下版本不支持 | 谷歌、火狐、Edge不支持,IE5-IE10支持 |
addEventListener中事件的类型(事件的名字)没有on | attachEvent中的事件的类型(事件的名字)有on |
addEventListener 中的this是当前绑定事件的对象 | attachEvent中的this是window |