<script type="text/javascript">
function start(){
var b=0;
function cd(){
++b;
console.log(b);
}
cd();
}
start();
start();
</script>
如题,为什么这个B都会弹出1,不应该是里面的cd函数引用这个B,不会被清除么。
function start()
{
var b=0;
function cd(){
++b;
console.log(b);
}
cd();
}
start();
start();
GC只会清理那些你绝对访问不到的变量。在我们写JS看来GC仅仅js引擎对js代码的优化,即使我们认为任何分配的变量都不会被回收也没有关系。
现在我们看看如何便会无法访问到一个变量。
JS(ES5.1)是函数作用域,也就说JS的函数执行一次才会生成一个作用域,而函数作用域的父作用域主要看函数定义所在的位置。如上代码,所有代码执行前只有一个作用域--全局作用域。其中定义了一个变量/函数(除了JS预定义的全局变量)--start
。
当第一次执行start
,这个时候会生成一级作用域,假设我们叫他start1
,其中定义了两个变量b
(然后被赋值为0),cd
。然后执行cd()
函数,首先在本作用域(start1)中查找cd
,当然是有喽。执行cd函数的时候也生成一级作用域,由于cd
是在start1
中定义的,因此,新生成的作用域的父作用域是start1
。当函数中使用了b
的时候,在本作用域没有,于是到start1
中去找,就找到了start1中的b
。那么引用的就是这个变量。
当再一次执行 start
,这个时候也会生成一级作用域,假设我们叫他start2
,其中定义了两个变量b
(然后被赋值为0),cd
(与start1
中的那两个变量没关系,只是重名)。然后执行cd()
函数,首先在本作用域(start2)中查找cd
,当然是有。执行cd函数的时候也生成一级作用域,由于cd
是在start2
中定义的,因此,新生成的作用域的父作用域是start2
。当函数中使用了b
的时候,在本作用域没有,于是到start2
中去找,就找到了start2中的b
。那么引用的就是这个变量。
这样函数执行完之后,我们就无法访问到 start1
中的 b和cd ,也无法访问到start2
中的b和cd了。因为:第一,代码不再他们的作用域中了,第二,他们也无法成为其他作用域的父(祖先)作用域。
如下代码,自己用上面的方式分析执行结果。
function start()
{
var b=0;
function cd(){
++b;
console.log(b);
}
return cd;
}
cd1 = start();
cd1();
cd1();
cd2 = start();
cd2();
cd2();
这种现象叫做闭包,详见我的另一个回答:https://.com/q/1010000004736...
chrome里面,这个确实是闭包
YDKJS里面也讲过这个东西
但是严格来讲,闭包应该是从一个函数A中返回了函数B,并且B有对A函数中变量的引用
你每次都申明了次b=0
闭包里面的函数不会立即清掉的 推荐你看个东西 http://www.cnblogs.com/wangfupeng1988/p/...
b是在start内部声明并赋值的,作用域在start内部,在下次调用时重新声明并重新赋值为0了。
你这就是闭包函数,每次引用都会重置内部变量,因此在你引用的时候都是更新内部变量,所以每次都会重新使得b=1;所以怎么样都会输出1,return方法也是一样的道理
b和cd都是定义在start里的
每次start执行,都定义了一个新的b和新的cd
感觉提主要的效果应该是这样
function start(){
var b=0;
function cd(){
++b;
console.log(b);
}
return cd;
}
var cd = start();
cd();
cd();