在Javascript中,什么是闭包(Closure)

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

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

例1。

<script type="text/javascript">

function sayHello2(name){

var text='Hello'+name;//localvariable

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); },可以把上例改成这样:

<scrip ttype="text/javascript">

function sayHello2(name){

var text='Hello'+name;//localvariable

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

return sayAlert;

}

var sy=sayHello2('never-online');

alert(sy.toString());

</script>

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

例2。

<scrip ttype="text/javascript">

function say667(){

//Localvariablethatendsupwithinclosure

var num=666;

var sayAlert=function(){alert(num);}

num++;

return sayAlert;

}

varsy=say667();

sy();

alert(sy.toString());

</script>

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

例3。

<scrip ttype="text/javascript">

function setupSomeGlobals(){

//Localvariablethatendsupwithinclosure

var num=666;

//Storesomereferencestofunctionsasglobalvariables

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

gIncreaseNumber=function(){num++;}

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

}

</script>

<button οnclick="setupSomeGlobals()">生成-setupSomeGlobals()</button>

<button οnclick="gAlertNumber()">输出值-gAlertNumber()</button>

<button οnclick="gIncreaseNumber()">增加-gIncreaseNumber()</button>

<button οnclick="gSetNumber(5)">赋值5-gSetNumber(5)</button>

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

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

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

例4。

<scrip ttype="text/javascript">

function buildList(list){

var result=[];

for(vari=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]);

//usingjonlytohelppreventconfusion-couldusei

for(var j=0;j<fnlist.length;j++){

fnlist[j]();

}

}

testList();

</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。

<scrip ttype="text/javascript">

function newClosure(someNum,someRef){

//Localvariablesthatendupwithinclosure

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=new Closure(40,{someVar:'never-online'})

var closure2=new Closure(99,{someVar:'BlueDestiny'})

closure1(4)

closure2(3)

</script>

 

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值