闭包概念
先引用一下官方解释:
用我的蹩脚英语翻译过来换成自己的理解就是:
闭包举例
可能上边解释还是有点抽象,那我拿实际的代码举个例子:
var name = "window";
function outer(){
var name = 'outer';
function inner(){
return name;
}
return inner;
}
alert(outer()());
可以试着在浏览器运行一下这段script,会发现,弹出框内容为outer。
我先解释这个过程大致发生了什么,再联系前面说的两点说说我对闭包的理解。
首先第一行定义了name变量,很容易理解,name就是属于当前的浏览的页面吧!(实际name就是在当前window底下的全局变量,至于window是什么变量,不懂的话就把它当做是当前页面所在的环境吧)。
第2行-第12行我们定义了outer函数。
再看看第13行发生了什么,outer()()这是什么语法???那我们先分解来看吧,outer()一般是干嘛呢?当然是执行outer函数然后返回一个值咯。那在这里返回值是什么呢?inner!好,那就是说outer() == inner,应该同意吧?
于是乎outer()() == inner(),
所以最后alert出来的值将会是inner函数返回的值。外语屋
乱了乱了,不是说过,在一对括号{}里算是一个域,在这个域里边定义的东西,在离开这个域之后就会被销毁吗?
上面这个观点是对的,但是这个就是javascript闭包强大的地方:它把本来要销毁的一些变量给挽救回来,继续放在内存里边,让后边可以调用这个闭包来获取这些变量。
回到例子上吧,我们在outer函数里边定义了inner函数,如果说你最后不把它返回并且复制给变量,这个inner函数就会被销毁了,但是我们在第13行将它抛出去给外界执行了!!!于是js解释器知道它被暴露在外头了,不应该被销毁,所以就留住它的所在的环境,也就是outer的这个域。里边的name也被留下来了。
执行outer()之后,我们获取了刚刚说被暴露在外边的inner函数了,紧接着执行inner(),于是inner就开始找寻name变量了,我们知道inner所在的环境被嵌套了2层,inner->outer->window,当然啦,按照我们就近原则,我们肯定现在inner里边找name变量,发现找不到,于是到outer那个环境去找,此时找到了name,把name返回给inner()调用处alert出来。(这里可以思考一下脚本找寻变量的过程,就可以知道过多地访问全局变量会经常要把时间消耗在搜索过程,所以尽量避免过多地访问全局变量,至于怎么做,比较简单的就是采用一个局部变量记录该全局变量并替换成访问该局部变量)