这个函数是一个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,因此就能实现我们想要的效果了。
总结的不好,见谅。
原文:http://www.cnblogs.com/jingubang/p/4632506.html