
关于闭包的理解问题,小白求大牛解答!!
function a(){
var n = 0;
function inc(){ //--------------A处
n++;
console.log(n);
}
return inc;
}
var c = a();
c(); //------------------B处
c();
--------------------------------------------
首先:A处 inc 被 return回来
在B处 执行 但B处在全局变量中执行 怎么会访问到n??
有人说inc()里面有作用域链可以访问到n
可是,
A处的inc()都没有执行只是声明,没有执行,那inc()上下文的作用域链也不会创建吧!
那是怎么访问的??我有点迷糊,求大神解释。
其次:就当有一个引用引用了A处 A处没有被清理。那么怎么解释 全局函数a 也被a这个函数名引用执行完毕却被清除(不是a还在么,又没有a=null)。
我这点知识点有点矛盾,求大神解释下。。 展开
首先应该深入的理解一下闭包的概念,维基百科上关于闭包的解释理解起来比较容易些,我把前面两段话简单的处理一下:
在程序语言中,闭包(Closure),又称词法闭包(Lexical Closure)或函数闭包(function closures),是引用了自由变量的函数。这个被引用的自由变量将和这个函数一同存在,即使已经离开了创造它的环境也不例外。闭包是由函数和与其相关的引用环境组合而成的实体。
在一些语言中,在函数中可以(嵌套)定义另一个函数时,如果内部的函数引用了外部的函数的变量,则可能产生闭包。运行时,一旦外部的函数被执行,一个闭包就形成了,闭包中包含了内部函数的代码,以及所需外部函数中的变量的引用。
理解了闭包之后,再来看你的第一个问题,虽然A处的inc函数只是声明,但是闭包在外层函数a执行的时候就已经生成,形成的闭包包括了内部函数的代码和所需外部变量的引用。根据定义,还有一点需要注意,即形成的闭包保存的是外部变量的引用,看下面的例子:
var arr = [];
for (var i=0; i<3; i++) {
arr[i] = return function() {
alert(i)
}
}
arr[0]();
arr[1]();
arr[2]();
每次都是弹出3,即闭包只记住外部变量存放在了哪里,在内部函数还没有执行前,它是不管你的值是什么的,任你怎么变,我执行的时候只获取最后的值。要想实现想要的效果,可以这样做:
var arr = [];
for (var i=0; i<3; i++) {
arr[i] = function(j) {
return function() {
alert(j)
}
}(i)
}
arr[0]();
arr[1]();
arr[2]();
这里用一个立即执行函数,使得每次循环的i值都记录下来了。
你的第二个问题看了好几遍还是不太理解你想问什么,简单的说一些常识吧。function a(...)和var a=function(...)是函数的两种声明方式,无论哪一种,只要你没有重新给a赋值,即a还指向这个函数,那么这个函数所占据的内存就不会被回收,函数执行完毕后回收的只是函数内部声明的局部变量(如果变量没有被内部函数引用形成闭包),故而函数的局部变量在函数每次执行时都重新定义,重新赋值。