javascript代码实例教程-javascript中闭包的详解

发布时间:2018-12-31 发布网站:脚本宝典
脚本宝典收集整理的这篇文章主要介绍了javascript代码实例教程-javascript中闭包的详解脚本宝典觉得挺不错的,现在分享给大家,也给大家做个参考。
小宝典致力于为广大程序猿(媛)提供高品质的代码服务,请大家多多光顾小站,小宝典在此谢过。

1.什么是闭包?

所谓闭包:在一个函数作用域中保留它上级作用域的局部变量,这些局部变量不会随着上级函数的执行完毕而被销毁。

简单的理解闭包:子函数可以使用父函数的局部变量(包括参数,因为参数也是局部变量);

[javascript]view plaincopy

functiontest(){

vari=0;

functionb(){

alert(++i);

}

returnb;

}

varc=test();

c();

闭包是和JS的垃圾回收机制(以下简写GC)相关的,正常来说在test()函数调用完毕后,为局部变量i分配的空间就会被GC回收了.但是这里在test函数里又定义了一个子函数b,并且在函数b的里面用到了上级函数的局部变量i,然后在test()里returnb. 这样一来就会导致:

当test()函数调用完毕,为局部变量i分配的空间也不会被GC收回。

所以在varc=test();这句执行完毕后,调用c()依然可以访问到局部变量i,所以就弹出了1.

[javascript]view plaincopy

functionparent(num1){

varnum2=10;

returnfunctionchild(){

alert(num1+num2);

}

}

varfun=parent(10);

fun();

在parent函数内部返回值也是一个函数,在return的这个child()函数里,用到了parent函数的参数num1和局部变量num2,因为形成了闭包,所以调用fun()的时候就可以访问到num1和num2.所以就弹出20了.

接着看一个稍微复杂的例子:

[javascript]view plaincopy

varname='zj';

varobj={

name:'z3',

getName:function(){

returnfunction(){

returnthis.name;

}

}

}

alert(obj.getName()());//弹出zj

为什么会弹出zj那?让我们一点点来看:

首选把alert里内容改成alert(obj.getName);看一下

javascript中闭包的详解

直接alert(obj.getName)就相当于调用obj这个对象下的getName属性,弹出getName这个属性的值,所以弹出是一大段代码接着改写成alert(obj.getName()),看下结果

javascript中闭包的详解

直接alert(obj.getName())就相当于直接执下面的代码:

[javascript]view plaincopy

function(){

returnfunction(){

returnthis.name;

}

}

而执行这个函数执行之后返回值又是一个函数,所以alert(obj.getName())还是一段函数代码[javascript]view plaincopy

function(){returnthis.name;} 接着把alert(obj.getName())改成alert(obj.getName()()),到这里就相当于直接运行[javascript]view plaincopy

varn=obj.getName();

alert(n());

这样弹出的结果也是zj

2.怎么样才能形成闭包?

在有函数嵌套的情况下,子函数用到了父函数的参数或者局部变量,一般都会形成闭包。

3.闭包有什么好处?

好处1:具有封闭性,可以起到保护变量的作用

[javascript]view plaincopy

//1级作用域

functionf(x){//2级作用域

vartemp=x;

returnfunction(x){//3级作用域

temp+=x;

alert(temp);

}

}

vara=f(50);

a(5);//55

a(10);

我们在二级作用域里定义了一个局部变量temp,然后再三级作用域里用到了这个变量,这里就形成了闭包,把temp这个变量保护起来,不被GC所回收,方便在以后再使用temp这个变量。[javascript]view plaincopy

vara=1;

functiontest(){

a++;

alert(a);

}

test();//调用一次a就加1

test(); 此时的a是全局变量,程序当中经可能的避免全局变量,此时把a提到内部,变成局部变量看一下[javascript]view plaincopy

functiontest(){

vara=1;

a++;

alert(a);

}

test();//2

test();//2

我们发现不管调多少次结果都是2.这也是因为每调用一次test();都会重新定义变量a=1,然后累加一次变成2,然后弹出就结束了;再调用test()还是重新定义变量a=1...,所以永远是弹出2;[javascript]view plaincopy

functiontest(){

vara=1;

functionb(){

a++;

alert(a);

}

returnb;

}

varc=test();//2

c();//2

c();

c();

再来看一个例子:

[html]view plaincopy

有4个li,当点击第一个li弹出0,点击第二个弹出1,点第三个弹出2,点第四个弹出3,[javascript]view plaincopy

000

111

222

333

这样写完之后发现每次点击弹出来都是4,因为当每次当我们点击li的时候,其实for循环已经循环结束了,所以每次都会弹出4。[javascript]view plaincopy

所以这样每次点击第一个li就会弹出0,点击第二个弹出1,点第三个弹出2,点第四个弹出3了[javascript]view plaincopy

window.onload=function(){

varoDiv=document.getElementById('p1');

oDiv.onclick=function(){

alert(oDiv.id);

}

}

varoDiv这个变量的onclick属性引用了一个匿名函数,而在这个函数内部又用到了oDiv.id的引用,因为oDiv是在这个匿名函数外部定义的,此时就会引起内存泄露;

2.那怎么解决内存泄露问题那??

[javascript]view plaincopy

window.onload=function(){

varoDiv=document.getElementById('p1');

oDiv.onclick=function(){

alert(oDiv.id);

}

window.onunload=function(){

oDiv.onclick=null;

}当页面跳转的时候把oDiv.onclick引用置为空就好了

}

或者是[javascript]view plaincopy

window.onload=function(){

varoDiv=document.getElementById('p1');

varid=oDiv.id;

oDiv.onclick=function(){

alert(id);

}

oDiv=null;

}

在内部匿名函数引用之前把oDiv.id通过一个变量接受一下,然后用完之后把oDiv置为空也可以解决内存泄露问题。

觉得可用,就经常来吧! 脚本宝典 欢迎评论哦! js脚本,巧夺天工,精雕玉琢。小宝典献丑了!

脚本宝典总结

以上是脚本宝典为你收集整理的javascript代码实例教程-javascript中闭包的详解全部内容,希望文章能够帮你解决javascript代码实例教程-javascript中闭包的详解所遇到的问题。

如果觉得脚本宝典网站内容还不错,欢迎将脚本宝典推荐好友。

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。
标签:HTML