闭包是一个比较抽象的概念, 尤其是对 js 新手来说. 书上的解释实在是比较晦涩, 对我来说也是一样. 闭包是很多语言都具备的特性, 在 js 中, 闭包主要涉及到 js 的几个其他的特性: 作用域链, 垃圾 (内存) 回收机制, 函数嵌套, 等等.
Javascript 是一种由 Netscape 的 LiveScript 发展而来的原型化继承的基于对象的动态类型的区分大小写的客户端脚本语言,主要目的是为了解决服务器端语言,比如 Perl,遗留的速度问题,为客户提供更流畅的浏览效果。
首先我们先来看一段代码:
- <a href="javascript:void(0);">
- 111
- </a>
- <a href="javascript:void(0);">
- 222
- </a>
- <a href="javacsript:void(0);">
- 333
- </a>
- var a=document.getElementsByTagName("a"); function b(){ for(var
- i=0;i
- <a.length;i++){ a[i].onclick=function(){ alert(i); } }
- }
按照我们设计的初衷,应该是点击一个 a 标签就相应的弹出该标签的序列号,即点击第一个 a 就弹出 0,点击第二个就弹出 1... 但是事实是弹出的始终是 a 标签的个数,这是什么原因呢?这个问题困扰了我很久,查阅了许多网上的资料还有参考书籍,大多说的似是而非,相信也有许多同学对其中原因也不甚了解,就这个问题我谈谈自己的理解,如有不当之处,还请批评指正。
就我个人的理解,上述函数未能达到目的的原因是,事件处理函数绑定了变量 i,而该事件处理函数又赋值给了 onclick,即是说只有在点击 a 标签的时候才会调用该函数,因此从逻辑上来说,在单纯的 for 循环里面 function(){alert(i);} 这段函数实际上是没有执行的,而当我们点击 a 标签的时候 for 循环早就已经执行完毕,此时 i 的值就是 for 循环执行完毕的终态值。通俗一点理解,就是这个 i 的值是属于 b 函数的,而我们需要的 i 的值是实时传递进事件处理函数中的值。那么有什么方法可以实现我们的设计初衷呢?聪明的同学可能已经猜到了,那就是使用闭包。
下面我们再来看一段代码:
- var a=document.getElementsByTagName("a");
- function b(){
- for(var i=0;i<a.length;i++){
- a[i].onclick=function(j){
- return function(){
- alert(j);
- }
- }(i);
- }
- }
- b();
执行以上代码可以发现,我们所要的功能已经实现,即点击任意 a 标签都会弹出该标签所在的序列号。对上述代码,相信许多同学都看过许多雷同的版本,但是为什么这样做就能实现我们需要的功能了呢,一下是个人的一点浅见,如有不当,还请不吝赐教。
对上述代码的理解,其本质就是对变量 i 的理解。在这段代码中,函数执行到 for 循环处发现了一个立即调用函数,这个时候给这个立即调用函数传递实时的 i 变量值,函数立即调用完成,事件处理函数也就存储了实时的 i 变量值。
以上所述就是本文的全部内容了,希望对大家理解 js 闭包能够有所帮助。
来源: