在Javascript中什么是闭包(Closure)

2016-02-19 22:17 6 1 收藏

下面请跟着图老师小编一起来了解下在Javascript中什么是闭包(Closure),精心挑选的内容希望大家喜欢,不要忘记点个赞哦!

【 tulaoshi.com - Web开发 】

  闭包的两个特点:

  1、作为一个函数变量的一个引用 - 当函数返回时,其处于激活状态。

  2、一个闭包就是当一个函数返回时,一个没有释放资源的栈区。

  例1。

  scripttype="text/javascript"

  functionsayHello2(name){

  vartext='Hello'+name;//localvariable

  varsayAlert=function(){alert(text);}

  returnsayAlert;

  }

  varsy=sayHello2('never-online');

  sy();

  /script

  作为一个Javascript程序员,应该明白上面的代码就是一个函数的引用。如果你还不明白或者不清楚的话,请先了解一些基本的知识,我这里不再叙述。

  上面的代码为什么是一个闭包?

  因为sayHello2函数里有一个内嵌匿名函数

  sayAlert = function(){ alert(text); }

  在Javascript里。如果你创建了一个内嵌函数(如上例),也就是创建了一个闭包。

  在C或者其它的主流语言中,当一个函数返回后,所有的局部变量将不可访问,因为它们所在的栈已经被消毁。但在Javascript里,如果你声明了一个内嵌函数,局部变量将在函数返回后依然可访问。比如上例中的变量sy,就是引用内嵌函数中的匿名函数function(){ alert(text); },可以把上例改成这样:

  scripttype="text/javascript"

  functionsayHello2(name){

  vartext='Hello'+name;//localvariable

  varsayAlert=function(){alert(text);}

  returnsayAlert;

  }

  varsy=sayHello2('never-online');

  alert(sy.toString());

  /script

  这里也就与闭包的第二个特点相吻合。

  例2。

  scripttype="text/javascript"

  functionsay667(){

  //Localvariablethatendsupwithinclosure

  varnum=666;

  varsayAlert=function(){alert(num);}

  num++;

  returnsayAlert;

  }

  varsy=say667();

  sy();

  alert(sy.toString());

  /script

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

  [

  例3。

  scripttype="text/javascript"

  functionsetupSomeGlobals(){

  //Localvariablethatendsupwithinclosure

  varnum=666;

  //Storesomereferencestofunctionsasglobalvariables

  gAlertNumber=function(){alert(num);}

  gIncreaseNumber=function(){num++;}

  gSetNumber=function(x){num=x;}

  }

  /script

  buttononclick="setupSomeGlobals()"生成-setupSomeGlobals()/button

  buttononclick="gAlertNumber()"输出值-gAlertNumber()/button

  buttononclick="gIncreaseNumber()"增加-gIncreaseNumber()/button

(本文来源于图老师网站,更多请访问http://www.tulaoshi.com/webkaifa/)

  buttononclick="gSetNumber(5)"赋值5-gSetNumber(5)/button

  上例中,gAlertNumber, gIncreaseNumber, gSetNumber都是同一个闭包的引用,setupSomeGlobals(),因为他们声明都是通过同一个全局调用——setupSomeGlobals()。

  你可以通过“生成”,“增加”,“赋值”,“输出值”这三个按扭来查看输出结果。如果你点击“生成”按钮,将创建一个新闭包。也就会重写gAlertNumber(), gIncreaseNumber(), gSetNumber(5)这三个函数。

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

  例4。

  scripttype="text/javascript"

  functionbuildList(list){

  varresult=[];

  for(vari=0;ilist.length;i++){

  varitem='item'+list[i];

  result.push(function(){alert(item+''+list[i])});

  }

  returnresult;

  }

  functiontestList(){

  varfnlist=buildList([1,2,3]);

  //usingjonlytohelppreventconfusion-couldusei

  for(varj=0;jfnlist.length;j++){

  fnlist[j]();

  }

  }

  testList();

(本文来源于图老师网站,更多请访问http://www.tulaoshi.com/webkaifa/)

  /script

  运行结果:

  item3isundefined

  item3isundefined

  item3isundefined

  代码result.push(function(){alert(item+''+list[i])}),

  使result数组添加了三个匿名函数的引用。这句代码也可以写成

  varp=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。

  scripttype="text/javascript"

  functionnewClosure(someNum,someRef){

  //Localvariablesthatendupwithinclosure

  varnum=someNum;

  varanArray=[1,2,3];

  varref=someRef;

  returnfunction(x){

  num+=x;

  anArray.push(num);

  alert('num:'+num+

  'anArray'+anArray.toString()+

  'ref.someVar'+ref.someVar);

  }

  }

  varclosure1=newClosure(40,{someVar:'never-online'})

  varclosure2=newClosure(99,{someVar:'BlueDestiny'})

  closure1(4)

  closure2(3)

  /script

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

来源:http://www.tulaoshi.com/n/20160219/1628094.html

延伸阅读
标签: Web开发
摘要 :现代网站和web应用程序趋向于依赖客户端的大量的 javascript 来提供丰富的交互。特别是通过不刷新页面的异步请求来返回数据或从服务器端的脚本(或数据系统)中得到响应。在这篇文章中,你将会了解到javascript框架如何更快、更方便的创建互动性强、响应快得网站和web应用程序。 导言 :JavaScript是一种面向对象的脚本语言,一直...
标签: 待产包清单
为了避免突发情况手忙脚乱,建议准妈妈们在怀孕七个月左右开始准备待产包。待产包清单主要包括妈妈和宝宝的用品,以及其它必备的东西。另外,根据季节的不同,待产包的准备也应做调整。那么具体该如何准备待产包,下面大家一起来看看吧。 什么...
标签: 电脑入门
在系统操作中,闭源软件和开源软件是相对的,总有人拿这2个比较优劣,有时需要在系统中安装鼻渊软件包,下面图老师小编就给大家介绍下Debian安装闭源软件包的方法。 Debian是一个拥有48,000软件包的发行版。 这些软件包被分为三类: main, contrib 和 non-free, 主要是根据许可证要求, 参照Debian开源软件指南 (DFSG)。 main软件仓...
标签: Web开发
!DOCTYPE HTML PUBLIC “-//W3C//DTD HTML 4.0 Transitional//EN“ HTML HEAD META http-equiv=Content-Type content=“text/html; charset=utf-8“ TITLE打开Excel表/TITLE /HEAD BODY input name=“shanghai“ type=“button“ class=“but“ id=“shanghai“&nbs...
标签: Web开发
一、什么是框架 框架Frames最主要功用是"分割"视窗,使每个"小视窗"能显示不同的HTM L文件,不同框架之间可以互动(interact),这就是说不同框架之间可以交换讯息与资料。例如:假设您开了两个frames,第一个frame可显示书的目录,第二个frame则显示章节的具体内容。 框架可以将屏幕分割成不同的区域,每个区...

经验教程

811

收藏

69
微博分享 QQ分享 QQ空间 手机页面 收藏网站 回到头部