浅谈js中的闭包

 闭包是一个比较抽象的概念,尤其是对js新手来说.书上的解释实在是比较晦涩,对我来说也是一样.闭包是很多语言都具备的特性,在js中,闭包主要涉及到js的几个其他的特性:作用域链,垃圾(内存)回收机制,函数嵌套,等等.

 
 

首先我们先来看一段代码:

 

代码如下:

<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闭包能够有所帮助。

时间: 2024-08-05 03:12:38

浅谈js中的闭包的相关文章

浅谈js中的闭包_javascript技巧

首先我们先来看一段代码: 复制代码 代码如下: <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");

浅谈JS中的!=、== 、!==、===的用法和区别_javascript技巧

var num = 1; var str = '1'; var test = 1; test == num //true 相同类型 相同值 test === num //true 相同类型 相同值 test !== num //false test与num类型相同,其值也相同, 非运算肯定是false num == str //true 把str转换为数字,检查其是否相等. num != str //false == 的 非运算 num === str //false 类型不同,直接返回fals

浅谈js中startsWith函数不能在任何浏览器兼容的问题

在做js测试的时候用到了startsWith函数,但是他并不是每个浏览器都有的,所以我们一般要重写一下这个函数,具体的用法可以稍微总结一下. 在有些浏览器中他是undefined 所以我们可以这样的处理一下 if (typeof String.prototype.startsWith != 'function') {    String.prototype.startsWith = function (prefix){    return this.slice(0, prefix.length)

浅谈JS中逗号运算符的用法_javascript技巧

注意: 一.由于目前正在功读JavaScript技术,所以这里拿JavaScript为例.你可以自己在PHP中试试. 二.JavaScript语法比较复杂,因此拿JavaScript做举例. 最近重新阅读JavaScript权威指南这本书,应该说很认真的阅读,于是便想把所学的东西多记录下来.后 面本人将逐步写上更多关于本书的文章. 本文的理论知识来自于JavaScript权威指南,我这里做一下整理,或者说叫笔记. 如果你的基础够好的话,完全理解不成问题,但是如果读得有些郁闷的话,可以加我的QQ:

浅谈js中StringBuffer类的实现方法及使用_javascript技巧

如下所示: <strong>JAVA中有一个StringBuffer类,js中却没有下面来自己实现一个简单的js的StringBuffer类.</strong> //创建一个StringBuffer类 ,此类有两个方法:一个是append方法一个是toString方法 function StringBuffer() { this.__strings__ = []; }; StringBuffer.prototype.append = function(str) { this.__s

浅谈JS中String()与 .toString()的区别_javascript技巧

我们知道String()与 .toString()都是可以转换为字符串类型,但是String()与 .toString()的还是有区别的 1..toString()可以将所有的的数据都转换为字符串,但是要排除null 和 undefined 例如将false转为字符串类型 <script> var str = false.toString(); console.log(str, typeof str); </script> 返回的结果为 false,string 看看null 和

浅谈JS中的bind方法与函数柯里化_javascript技巧

绑定函数bind()最简单的用法是创建一个函数,使这个函数不论怎么调用都有同样的this值.不同于call和apply只是单纯地设置this的值后传参,它还会将所有传入bind()方法中的实参(第一个参数之后的参数)与this一起绑定. 关于这个特性看<JS权威指南>原文的例子: var sum = function(x,y) { return x + y }; var succ = sum.bind(null, 1); //让this指向null,其后的实参也会作为实参传入被绑定的函数sum

浅谈js中对象的使用_javascript技巧

简单记录javascript中对象的使用 一.创建对象 //创建一个空对象 var o={}; //创建一个含有两个属性的对象,x.y var o2={x:12,y:'12',name:'JS'}; //此对象中的author属性的值还是一个对象 var o3={x:12,author:{name:'JS',age:23,address:'china'}}; //创建一个空对象和{}一样 var o4=new Object(); //给对象增加name属性 o4.name='JS' 上面使用了两

浅谈js中test()函数在正则中的使用_javascript技巧

test() 方法用于检测一个字符串是否匹配某个模式. 返回一个 Boolean 值,它指出在被查找的字符串中是否匹配给出的正则表达式. regexp.test(str) 参数 regexp 必选项.包含正则表达式模式或可用标志的正则表达式对象. str    必选项.要在其上测试查找的字符串. 说明 test 方法检查字符串是否与给出的正则表达式模式相匹配,如果是则返回 true,否则就返回 false. 每个正则表达式都有一个 lastIndex 属性,用于记录上一次匹配结束的位置. var