设为首页 友情链接
在线留言 发表文章
加入收藏 广告联系

刺猬首页

| 专案技术 | 网络技术 | 图形图象 | 网络编程 | 网页设计 | 操作系统 | 服务器 | 技术白皮书 | 在线实验室 | 刺猬论坛 |
小说专版  | 数据库 | 设计赏析 | 存储频道 | 网络安全 | 私服架设 |  Solaris | 网站评估 | PC维护技巧 | 下载中心 | 博 客 |
专   题: | Linux | java | cisco | 防病毒 | 刀片 | SOA | iscsi | ASP.NET | SQL | Oracle |
您现在的位置: IT公社 IT community >> 网络编程 >> JS 技术 >> 教程正文 用户登录 新用户注册
专 题 栏 目
最 新 热 门
最 新 推 荐
相 关 文 章
javascript设计网页…
通过PHP和Sajax使用Ajax…
在CSS样式表里使用j…
在ASP.NET页面上轻松整合…
FireFox 如何用java…
实例:尽可能写友好的&#…
搜索引擎页面分析中的 &…
浅谈javascript中面…
理解javascript中的…
javascript数组 sor…
  在javascript中,什么是闭包(Closure)           
在javascript中,什么是闭包(Closure)
 

闭包的两个特点:

1、作为一个函数变量的一个引用 - 当函数返回时,其处于激活状态。
2、一个闭包就是当一个函数返回时,一个没有释放资源的栈区。

例1。 <script type="text/javascript">
function sayHello2(name) {
 var text = 'Hello ' + name; // local variable
 var sayAlert = function() { alert(text); }
 return sayAlert;
}
var sy = sayHello2('never-online');
sy();
</script>
作为一个Javascript程序员,应该明白上面的代码就是一个函数的引用。如果你还不明白或者不清楚的话,请先了解一些基本的知识,我这里不再叙述。

上面的代码为什么是一个闭包?
因为sayHello2函数里有一个内嵌匿名函数
sayAlert = function(){ alert(text); }
在Javascript里。如果你创建了一个内嵌函数(如上例),也就是创建了一个闭包。

在C或者其它的主流语言中,当一个函数返回后,所有的局部变量将不可访问,因为它们所在的栈已经被消毁。但在Javascript里,如果你声明了一个内嵌函数,局部变量将在函数返回后依然可访问。比如上例中的变量sy,就是引用内嵌函数中的匿名函数function(){ alert(text); },可以把上例改成这样: <script type="text/javascript">
function sayHello2(name) {
 var text = 'Hello ' + name; // local variable
 var sayAlert = function() { alert(text); }
 return sayAlert;
}
var sy = sayHello2('never-online');
alert(sy.toString());
</script>这里也就与闭包的第二个特点相吻合。

例2。 <script type="text/javascript">
function say667() {
 // Local variable that ends up within closure
 var num = 666;
 var sayAlert = function() { alert(num); }
 num++;
 return sayAlert;
}

var sy = say667();
sy();
alert(sy.toString());
</script>
上面的代码中,匿名变量function() { alert(num); }中的num,并不是被拷贝,而是继续引用外函数定义的局部变量——num中的值,直到外函数say667()返回。

例3。 <script type="text/javascript">
function setupSomeGlobals() {
 // Local variable that ends up within closure
 var num = 666;
 // Store some references to functions as global variables
 gAlertNumber = function() { alert(num); }
 gIncreaseNumber = function() { num++; }
 gSetNumber = function(x) { num = x; }
}

</script>
<button onclick="setupSomeGlobals()">生成 - setupSomeGlobals()</button>
<button onclick="gAlertNumber()">输出值 - gAlertNumber()</button>
<button onclick="gIncreaseNumber()">增加 - gIncreaseNumber()</button>
<button onclick="gSetNumber(5)">赋值5 - gSetNumber(5)</button>
上例中,gAlertNumber, gIncreaseNumber, gSetNumber都是同一个闭包的引用,setupSomeGlobals(),因为他们声明都是通过同一个全局调用——setupSomeGlobals()。
你可以通过“生成”,“增加”,“赋值”,“输出值”这三个按扭来查看输出结果。如果你点击“生成”按钮,将创建一个新闭包。也就会重写gAlertNumber(), gIncreaseNumber(), gSetNumber(5)这三个函数。

如果理解以上代码后,看下面的例子:

例4。 <script type="text/javascript">
function buildList(list) {
 var result = [];
 for (var i = 0; i < list.length; i++) {
 var item = 'item' + list[i];
 result.push( function() {alert(item + ' ' + list[i])} );
 }
 return result;
}

function testList() {
 var fnlist = buildList([1,2,3]);
 // using j only to help prevent confusion - could use i
 for (var j = 0; j < fnlist.length; j++) {
 fnlist[j]();
 }
}

testList();
</script>
运行结果:
item 3 is undefined
item 3 is undefined
item 3 is undefined

代码result.push( function() {alert(item + ' ' + list[i])} ),
使result数组添加了三个匿名函数的引用。这句代码也可以写成
var p = function() {alert(item + ' ' + list[i])};
result.push(p);

关于为什么会输出三次都是 "item 3 is undefined"

在上面的例子say667()例子中已经解释过了。
匿名函数function() {alert(item + ' ' + list[i])}中的list[i]并不是经过拷贝,而是对参数list的一个引用。直到函数buildList()返回为止,也就是说,返回最后一个引用。即遍历完list(注:list的最大下标应该是2)后,经过i++也就变成了3,这也就是为什么是item 3,而list[3]本身是没有初始化的,自然也就是undefined了。

例5。 <script type="text/javascript">
function newClosure(someNum, someRef) {
 // Local variables that end up within closure
 var num = someNum;
 var anArray = [1,2,3];
 var ref = someRef;
 return function(x) {
 num += x;
 anArray.push(num);
 alert('num: ' + num + 
 '\nanArray ' + anArray.toString() + 
 '\nref.someVar ' + ref.someVar);
 }
}
var closure1 = newClosure(40, {someVar:' never-online'})
var closure2 = newClosure(99, {someVar:' BlueDestiny'})
closure1(4)
closure2(3)
</script>


在这最后一个例子中,展示如何声明两个不同的闭包。

频道声明:本频道的文章除部分特别声明禁止转载的专稿外,可以自由转载.但请务必注明出出处和原始作者 文章版权归本频道与文章作者所有.对于被频道转载文章的个人和网站,我们表示深深的谢意。

原始作者:佚名 录入时间:2006-12-5 3:08:03
信息来源:不详 投稿信箱:itqoo@126.com
教程录入:itqoo    责任编辑:itqoo 
  • 上一个教程:

  • 下一个教程: 没有了
  • 【字体: 】【发表评论】【加入收藏】【告诉好友】【打印此文】【关闭窗口
      网友评论:(只显示最新10条。评论内容只代表网友观点,与本站立场无关!)
    - 关于我们 - 合作伙伴 - 友情链接 - 广告刊登 - 投稿热线 - 在线留言版权声明联系方式 -
    IT公社版权所有 粤ICP备05127012号
    Copyrigh@2005-2006 itqoo.com.Inc All Rights Reserved  推荐分辨率 1024*768
    联系站长:E-Mail:itqoo@126.com     MSN:urchincc@hotmail.com    QQ:点击这里给我发消息
    特别感谢:亿太网络提供空间支持