首页 > 其他 > 详细

DOM的addEventListener函数一个陷阱。

时间:2015-07-09 12:51:55      阅读:251      评论:0      收藏:0      [点我收藏+]

这个函数是一个DOM Level3级方法,注册事件的,用法是:

DOM对象.addEventListener("事件名称(比如click)",事件执行的函数(可以是匿名函数或者函数名),false/true(false表示冒泡方式,true表示捕获方式));

这里注意第二个参数好像不是立即就编译进去(当然JS是没有编译的东西的,只是为了表述),而是在事件触发的时候才运行里边的代码,包括变量赋值。

比如下边代码

<a href="###">连接一</a>
<a href="###">连接二</a>
<a href="###">连接三</a>
<a href="###">连接四</a>
<a href="###">连接五</a>
<a href="###">连接六</a>
<a href="###">连接七</a>
<a href="###">连接八</a>
<a href="###">连接九</a>

<script>
var myHref = document.getElementsByTagName("a");
for (var i = 0,mylength = myHref.length; i<mylength; i++) {
    myHref[i].addEventListener("click",function(e){
        e.preventDefault();
        alert(i);
    },"false");
}
</script>

我们希望的结果是点击每一个a会弹出对应的数组标号值,也就是第一个a点击后显示0,第二个显示1。但是实际上我们发现并不是这个结果,而是总是显示最后一个a标签对象的数组标号值+1,也就是9。

所以我认为,函数并不是立即执行,而只是发函数的引用放在那了,当事件发生的时候,才去调用实际的函数体,而且i做为全局变量,一直保存了下来,如果我们最后对i进行了别的操作,比如这样:

<script>
var myHref = document.getElementsByTagName("a");
for (var i = 0,mylength = myHref.length; i<mylength; i++) {
    myHref[i].addEventListener("click",function(e){
        e.preventDefault();
        alert(i);
    },"false");
}
i=555;
</script>

每一个连接弹出的就是555了。实际i是做为全局变量的(js没有块作用域,所以for循环内的i不是局部变量,而是全局变量),我又想,如果我把i让内存回收掉,是不是就会报错了,结果我试了一下并不能回收,可能是因为闭包的关系。其实浏览器里即使是全局函数都是一个闭包,具体为什么我这里理解,大家可以找一找闭包的相关资料看一下。

那么如何实现我们想要的效果,还是得用到闭包啊,我们需要把当时的i保存下来。代码如下:

<script>
var myHref = document.getElementsByTagName("a");
for (var i = 0,mylength = myHref.length; i<mylength; i++) {
    (function(i){  //这里的i跟外部的i实际不是一个i
        myHref[i].addEventListener("click",function(e){
            e.preventDefault();
            alert(i);
        },"false");
    })(i);
}
i=555;    //不会影响
</script>

这样写,实际上for循环里是一个立即执行的函数表达式,这种写法()();是立即执行了,立即执行我们的闭包,我们把i当参数传给闭包,闭包里边的i实际作用域只在闭包里,跟外部的i不是一个i,因此就能实现我们想要的效果了。

总结的不好,见谅。

DOM的addEventListener函数一个陷阱。

原文:http://www.cnblogs.com/jingubang/p/4632506.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!