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
references
counter