js函数闭包学习贴

最后一个菜鸟 2012-03-15 06:34:21
加精
前几天看了《javascript语言精髓与编程实践》对函数闭包的讲解,很有感触,跟大家分享一下。



其实js支持函数闭包的主要原因是因为js需要函数能够保存数据。这里的保存数据是只函数在运行结束以后函数内变量的值也会进行保存。至于为什么js需要在函数内可以保存数据,那就是js是一种函数式语言。在函数内保存数据是函数式语言的一大特征。上代码:

var getValue,setValue;
function test(){
var value=100;
getValue=function (){
return value;
}
setValue =function (x){
value=x;
}
}
test();
alert(getValue());//输出100

setValue(200);//设置value

alert(getValue());//输出200



上例表明函数内部可以保存数据,而这是通过函数闭包实现的。



函数闭包是一个运行时的概念。函数闭包对应函数实例。而一个函数定义可能会对应多个函数实例。那么在什么情况下会返回不同的函数实例呢?


function getFunction(){

return function (){

alert(value);

}

}

var func1=getFunction();

var func2=getFunction();

alert(func1==func2)//输出false,表示是两个不同的函数应用。




很多情况下使用的都是不同的函数实例。比如在使用函数作为构造函数时。其实在不同情况下返回不同的函数实例也是可以解释的。后面我们会说到。



每一个函数实例对应至少一个函数闭包。对应一个闭包居多。故先说明对应一个函数闭包。

基本一个函数运行一次就会建立函数闭包。

闭包的实现其实很类似于js对象的实现。函数闭包建立时会将函数内声明的变量登记进一个表中。当函数内存取值时就会查阅此表,表中没有相关变量时就会去父类的闭包中寻找,直至最上层闭包,即最外层所在的闭包。


var value=1;

function test(){

var value=7;

function inline(){

var value=4;

alert(value);

}

inline();

}

test();//输出4



上面总共有三个闭包。一个全局闭包,该闭包中仅登记了一个变量value。test实例一个闭包,该闭包中也登记了一个value变量。inline实例一个闭包,该闭包同样也是只登记了一个value变量。三个闭包间的关系:全局闭包是test实例闭包的父闭包,test实例闭包是inline实例闭包的父闭包。所以输出4。

稍加修改

var value=1;

function test(){

function inline(){

alert(value);

}

}

test();//输出1



以上面的说明同样是可以解释的。上面的说明同样可以解释js函数中的一个规定。当在函数内不用var声明变量时,该变量被认为是全局变量。因为不使用var,函数内部先在自己的闭包内寻找变量,直至最上层闭包也没有寻找到,故在最上层(全局)声明该变量。
闭包的生存周期:当前闭包内没有任何值被应用,该闭包即销毁。


var getFunc;
function test(){
var func= function (){

alert(‘new function ’);
}
getFunc=function (){

return func;
}
}
test();

var func1=getFunc();

var func2=getFunc();

alert(func1==func2)//输出true;

上例中运行test,为test函数实例建立闭包。并对全局变量getFunc赋值。因为getFunc中含有对test实例函数闭包func的引用,所以该闭包不会被销毁,所以返回的总是同一个函数func的引用。还有一个更为典型的例子:

var checkre;
function myFunc(){

if(checker){

checker();

}
alert(‘myFunc:’+str);
var str=’ test’;
if(!checker){
checker=function (){
alert(‘checker:’+str);
}
}
return arguemnts.callee;//返回当前运行函数的引用
}
myFunc()();//myFunc连续运行两次。

结果是

myFunc :undefined

checker: test

myFunc:undefined

上面提到函数每()运行一次,就会建立一个函数闭包。故上例总共为myFunc先后建立了两个函数闭包。第一个函数运行结束后,输出结果第一行,checker被赋值,str登记在此闭包中,因为checker引用str,故第一个函数闭包不会销毁。当函数第二次运行时,checker有值,故运行,但是checker内引用的是第一个闭包内的str=‘test’,故会输出第二行的内容。然后myFunc输出结果第三行,因为此时str引用的当前闭包内的str,故为undefined。

最上面的getFunction的例子。每次都返回一个函数实例,是因为每次都建立一个闭包。

运行时存在函数闭包链,提供对函数外定义的变量的访问。
第一次写,有点散,希望对大家有帮助。
...全文
4403 102 打赏 收藏 转发到动态 举报
写回复
用AI写文章
102 条回复
切换为时间正序
请发表友善的回复…
发表回复
after9 2012-08-29
  • 打赏
  • 举报
回复
咋感觉越看越糊涂了呢
nieyijie0425 2012-08-16
  • 打赏
  • 举报
回复
学习了。。。
piaomiaowc 2012-08-14
  • 打赏
  • 举报
回复
支持,学习
l416685690 2012-08-03
  • 打赏
  • 举报
回复
CSDN高手真多
  • 打赏
  • 举报
回复
弱的问下..
哪里设置昵称?
shuo021 2012-03-29
  • 打赏
  • 举报
回复
这个就叫做闭包啊,学习了
广州接入 2012-03-26
  • 打赏
  • 举报
回复
把函数看作是对象就可以了.
jingyanzhi 2012-03-25
  • 打赏
  • 举报
回复
好东西,有收获,谢了
小马甲在code 2012-03-23
  • 打赏
  • 举报
回复
看来我太笨了,有点不解。
dying318 2012-03-23
  • 打赏
  • 举报
回复
写得挺好的,容易理解
Jonly 2012-03-23
  • 打赏
  • 举报
回复
灵若仙 2012-03-23
  • 打赏
  • 举报
回复
看的懂一点的!
berggi 2012-03-23
  • 打赏
  • 举报
回复
收藏了,下来慢慢看。
zhou648910133 2012-03-22
  • 打赏
  • 举报
回复
貌似! 看的懂一点的!
bijie521yl 2012-03-21
  • 打赏
  • 举报
回复
这是种机制,不多用下,很难理解透彻!
baidu2222222 2012-03-21
  • 打赏
  • 举报
回复
忘写了。。。。我看的也是这本书
baidu2222222 2012-03-21
  • 打赏
  • 举报
回复
老实说,闭包这东西非常有用。。。
cdcjk 2012-03-20
  • 打赏
  • 举报
回复
学习了!谢谢学习了!谢谢
  • 打赏
  • 举报
回复
刚好碰到一个使用闭包的例子:

setTimeout函数里给要调用的函数传递参数,setTimeout(myfunc(parameter), timeout)不行

setTimeout(myfunc, timeout, parameter)可以,但是在IE浏览器下不行,需要用闭包:

setTimeout(function(){myfunc(parameter);}, timeout);

(参考)
  • 打赏
  • 举报
回复
楼上评价的很中肯。
比如这种代码:
var value=1;

function test(){

var value=7;

function inline(){

var value=4;

alert(value);

}

inline();

}

test();//输出4

纯粹是javascript设计的失败之处,据说ecma 6可能会有所纠正。
加载更多回复(37)

87,989

社区成员

发帖
与我相关
我的任务
社区描述
Web 开发 JavaScript
社区管理员
  • JavaScript
  • 无·法
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧