为什么以及何时未执行的闭包可以捕获javascript中的外部变量?

为什么以及何时未执行的闭包可以捕获javascript中的外部变量?,javascript,node.js,garbage-collection,closures,v8,Javascript,Node.js,Garbage Collection,Closures,V8,我不明白为什么一个未执行的闭包可以捕获外部变量 我确实读过一些关于执行上下文、词汇环境、内存管理的文章,但这些都不能解决我的问题: function foo() { var a = 1; return function() { console.log(a); } } var f = foo() // line 7 // HERE variable a was been captured f = undefined // line 10 // HEAE variable a

我不明白为什么一个未执行的闭包可以捕获外部变量

我确实读过一些关于执行上下文、词汇环境、内存管理的文章,但这些都不能解决我的问题:

function foo() {
  var a = 1;
  return function() {
    console.log(a);
  }
}
var f = foo() // line 7
// HERE variable a was been captured

f = undefined // line 10
// HEAE variable a was been released
当引擎执行到第7行时,foo执行上下文是在全局执行上下文之上创建的,但在第7行之后,闭包从未执行过,因此闭包执行上下文从未创建过,词法环境也从未创建过。弹出foo执行上下文,变量a将被释放

我找不出我的观点有什么问题。 那么为什么以及何时捕获闭包中的变量呢

function foo() {
  var a = 1;
  return function() {
    console.log(a);
  }
}
函数内部的函数称为闭包。 当一个函数中有另一个函数,在这种情况下,顶层函数有一些类似于“a”的数据,那么所有内部函数都将访问该数据,只有当内部函数有一些关于这些变量的引用时,才会发生这种情况。 比如说,如果在“a”旁边有“b”变量,并且在内部函数中没有使用它,javascript将忽略它“闭包”不会像“a”一样保存此值。 这实际上是闭包赋予开发者力量的地方。请查看下面的示例-

希望这有帮助


谢谢。

以下是与您的问题相关的关于bugs.chromium的讨论。这样,即使else块从未执行,对else块返回的函数中使用的外部对象的引用也会创建并存储在堆中。它从不被垃圾收集。请参阅以下讨论:-

关键是词汇范围:

词法作用域是JavaScript语言使用的作用域模型,与其他一些使用动态作用域的语言不同。词法范围是在词法分析时定义的范围

考虑到这一点:

var a = 1
console.log(a)

console.log(b)
var b = 2

console.log(c)
您可以得到以下结果:

1
undefinded
ReferenceError: c is not defined
因此,您可以看到JavaScript是如何处理变量的:所有变量都是在词法分析时定义的,而赋值是在运行时定义的。这就是他们所说的提升

回到问题:闭包在词法转换时捕获变量,js引擎在其中读取代码和定义的变量并绑定它们


阅读有关编译的更多信息:

如果f在下面一行被调用,您希望何时捕获变量?闭包是在调用foo时创建的。它怎么知道你永远不会使用它?@Bergi还有一个问题:ExecutionContext是在函数调用时创建的还是在函数声明时创建的?@Barmar ExecutionContext是在函数调用时创建的还是在函数声明时创建的?@TaoPaipai调用函数时会创建一个执行上下文堆栈框架。但创建函数时,会在函数对象上捕获词法环境范围。编译时不一定与定义时相同。闭包在创建时捕获变量,而不是在编译其主体时。这个答案即使不是完全错误,也是严重误导。闭包是函数值的运行时表示形式。每次计算函数表达式时,都会创建它。
1
undefinded
ReferenceError: c is not defined