这主要是一个好奇心问题.考虑以下功能
var closure ;
function f0() {
var x = new BigObject() ;
var y = 0 ;
closure = function(){ return 7; } ;
}
function f1() {
var x = BigObject() ;
closure = (function(y) { return function(){return y++;} ; })(0) ;
}
function f2() {
var x = BigObject() ;
var y = 0 ;
closure = function(){ return y++ ; } ;
}
Run Code Online (Sandbox Code Playgroud)
在每种情况下,在执行函数之后,(我认为)无法到达x,因此BigObject可以被垃圾收集,只要x是对它的最后一个引用.只要评估函数表达式,一个简单的解释器就会捕获整个范围链.(首先,你需要这样做来调用eval工作 - 下面的例子).更智能的实现可能会在f0和f1中避免这种情况.更智能的实现将允许保留y,但不保留 …
作为ECMAScriptv5,每当控件输入代码时,enginge创建一个LexicalEnvironment(LE)和一个VariableEnvironment(VE),对于功能代码,这两个对象是完全相同的引用,它是调用NewDeclarativeEnvironment(ECMAScript v5 10.4)的结果. 3),在函数代码中声明的所有变量都存储在VariableEnvironment(ECMAScript v5 10.5)的环境记录组件中,这是闭包的基本概念.
令我困惑的是Garbage Collect如何使用这种闭包方法,假设我有以下代码:
function f1() {
var o = LargeObject.fromSize('10MB');
return function() {
// here never uses o
return 'Hello world';
}
}
var f2 = f1();
Run Code Online (Sandbox Code Playgroud)
在该行之后var f2 = f1(),我们的对象图将是:
global -> f2 -> f2's VariableEnvironment -> f1's VariableEnvironment -> o
Run Code Online (Sandbox Code Playgroud)
从我的小知识来看,如果javascript引擎使用引用计数方法进行垃圾收集,则该对象o至少有1次重新引用,并且永远不会被GCed.显然这会导致浪费内存,因为o永远不会被使用但总是存储在内存中.
有人可能会说引擎知道f2的VariableEnvironment …