您的位置:首页 > Web前端 > JavaScript

理解js闭包(closure)

2013-08-20 18:37 281 查看
最近在学习和理解js闭包,感觉闭包在编程开发中有着很好和很明确的指向,让一些功能模块和变量之间的联系跟明确,也可以让两个模块之间有明确的界限,至少是在编程和看别人代码的时候。

我简单的说一下我自己对闭包的理解吧,闭包很简单,要理解闭包,我们就必须要先弄清楚js中变量的作用域,js中的变量有全局变量和局部变量的区别,全局变量就是在这个js程序代码中,任何函数都可以调用改变的变量,而且,只要不给全局变量赋值为null,全局变量就会一直的占用内存空间,而局部变量呢?局部变量只能在自己所在的函数里被调用和改变,其他函数是不可以调用和改变的,并且,当本函数执行结束之后,这个局部变量也随之消失,并且也不在占用内存空间。而闭包是什么呢,简单的一句话就是,让外部函数调用和改变内部函数的变量的解决方法,下面我们来看看闭包是解决这个问题的,并且对闭包深入的了解。

下面我们看一段代码:

function f1(){
var n=1;
addnum=function(){n+=1} // 此为全局函数 前面没有var
function f2(){
alert(n);
}
return f2;
}
var res=f1();
res();//打印出1
addnum(); //注意这个方法
res(); // 打印出2

运行此代码,可以知道,第一次打印出来的局部变量n是1,第二次打印出来的局部变量n是2。如果我们按照常规的思路会发现,我们会认为,当我们执行完上面的addnum()函数之后,内存会释放变量n的空间,但是,事实不是这样的,因为我们定义的addnum函数是全局的,那么函数f1就时刻链接到了外部,我们可以理解成在执行f1函数时,函数时刻都在等待执行addnum函数,所以f1函数的通道打开之后就没有关闭,时刻链接到了外部,因为这个通道没有关闭,所以n变量的内存空间也就没有释放。这个代码中还有一处也是运用了闭包的机制,那就是在f1函数中return f2,f1函数返回的不是一个变量,而是一个函数指针,由于我们返回的是一个函数指针,所以我们在任何时候调用res()的时候,都会指向f2函数,这也是一个通道,将f1函数中的一个方法的指针传到外部,通过外部就可以对f1函数内部进行函数和功能的调用,这就是闭包。所以我们对闭包的写法简单的有两种,一种就是上面说到的设置全局函数addnum,一种就是返回内部函数指针,return f2。

其实闭包没有我们想的那么复杂,但是也没有那么简单,闭包是一种思想,他能解决我们外部调用内部的问题,也解决了变量污染,在几个人分别开发模块的时候,用闭包是很好的习惯,这样会大大降低代码中变量的污染。举个例子吧,当我们执行一个函数内部的功能时候,我们需要通过判断是否执行,我们可以通过对一个全局变量的改变来进行对这个功能的实现,有了闭包,我们就可以通过在函数内部写一个改变其局部变量的方法,在通过这个局部变量来控制某个功能的判断,从而避免了写全局变量带来的变量污染。因为我们的某些全局变量只是为了某些功能所定义的,我们就完全可以通过闭包来实现。

有人认为闭包的一个缺点是对内存的消耗,因为闭包中的变量没有释放,会长时间的占据内存空间,但是我觉得这个不是闭包的问题,而是书写代码人的问题。因为我们都有这样的一个想法,我们在写全局变量的时候,都会尽量的少写,或不写,但在闭包上,为什么我们不能有这样的想法呢,闭包中的变量某些地方其实有着和全局变量共同的特点,只是说,闭包把变量的具体作用体现在了内部函数,而把控制交给了外部,在避免变量污染的同时,又解决了外部控制问题,在内存上,闭包中的变量和全局变量有着共同的特性,所以我们应该在非得用全局变量的时候建议再使用闭包来解决问题。

总的来说,闭包就是打开一个通道,让外部可以对函数的内部进行变量的控制,突破作用域,这和在面向对象中封装是截然不同的,封装是对外关闭自己内部的可见性,让外部完全不能操作控制内部函数的机制,只通过接口传参,而闭包测可以通过外部来进行控制,改变内部函数的功能或者是机制,对外部提供了一个改变自己功能或者是属性的一个通道,当这个通道一直开着的时候,可以说这个函数是没有结束的,这个函数内部的局部变量也是始终占据着空间的。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: