JavaScript执行上下文和闭包
我试图深入理解闭包。从以下例子考虑:JavaScript执行上下文和闭包,javascript,Javascript,我试图深入理解闭包。从以下例子考虑: var add=(函数outerAdd(){ var计数器=0; 返回函数innerAdd(){ 计数器+=1; 返回计数器 } })(); log(add()); log(add()); log(add()); //计数器现在为3 页面上写着 不要使用学校。真正地这是一个糟糕的网站,几乎每件事都解释得很糟糕 变量存在,直到不再有任何引用它为止 计数器由内部添加引用,因此计数器将一直存在,直到内部添加不再存在。由于innerAdd从outerAdd返回并
var add=(函数outerAdd(){
var计数器=0;
返回函数innerAdd(){
计数器+=1;
返回计数器
}
})();
log(add());
log(add());
log(add());
//计数器现在为3
页面上写着
不要使用学校。真正地这是一个糟糕的网站,几乎每件事都解释得很糟糕
变量存在,直到不再有任何引用它为止
计数器
由内部添加
引用,因此计数器
将一直存在,直到内部添加
不再存在。由于innerAdd
从outerAdd
返回并分配给add
,因此它将继续存在,直到(在您的示例中)程序结束
若计数器是一个对象呢
计数器
是一个变量。在您的示例中,它的值是一个数字。如果该值是对某个对象的引用,那么它将以完全相同的方式工作。与往常一样,该值不太准确。它试图将这一描述用于
function add() {
var counter = 0;
counter += 1;
}
其中,counter
是一个局部变量,而且,一旦add
的调用完成,因为其他任何东西都不可能再引用该内部计数器
变量,它将很快被垃圾回收。但是仅仅因为变量是局部变量并不意味着它不再可引用/被删除,正如您问题中的代码所示。在大多数情况下,只有当没有其他变量可以引用它时,才会对变量进行垃圾收集(从内存中删除)
当innerAdd
函数运行时,不会复制该值-相反,IIFE范围内的旧计数器
变量仍然存在,因为调用innerAdd
仍将能够查看计数器
变量,因此计数器
变量不会得到GC'd
另外,若计数器是一个对象呢?那么,“复制”行为将如何运作?对象在JavaScript中通过引用进行复制
无论变量是原语还是对象,闭包和垃圾收集的工作方式都是相同的,例如,如果计数器
是数组,并且在每次调用时都被推送到数组,则会发生相同的情况:
(()=>{
var add=(函数outerAdd(){
var-arr=[];
返回函数innerAdd(项){
arr.push(项目);
}
})();
//在这里,“arr”变量仍然存在,因为它可以被“add”函数看到
增加(5);
增加(3);
增加(5);
})();
//这里,由于'add'函数不再是可引用的,其他任何函数都不能引用'arr',
//“arr”将被垃圾回收
函数完成时不会删除变量,不再需要时会删除变量。如果它们仍然被闭包引用,则不会被删除。但我仍然不知道innerAdd
的作用域链究竟何时引用了counter
?如果它是在执行innerAdd
期间(即为innerAdd
形成执行上下文时),那么为什么计数器当时仍然没有垃圾收集?当outerAdd
完成执行后,没有任何引用计数器
“但我仍然不明白innerAdd的作用域链究竟何时引用了计数器?”-计数器+=1
和返回计数器
“如果它是在执行innerAdd期间(即,为innerAdd形成执行上下文时),那么为什么当时计数器仍然没有被垃圾收集?”-因为分配给添加
(一个函数)的值仍然存在并继续使用该变量。“一旦outerad完成执行,就没有任何引用计数器”-正如我在回答中所说,innerAdd
referencescounter