简单的回答:如果str
没有从其他任何地方引用 的值(并且str
它本身也没有从 引用restofprogram
),那么一旦function (str) { ... }
返回,它将变得无法访问。
详细信息:V8 编译器将真正的局部变量与闭包捕获的所谓上下文变量区分开来,由with语句或eval
调用遮蔽。
局部变量存在于堆栈中,并在函数执行完成后立即消失。
上下文变量存在于堆分配的上下文结构中。当上下文结构消失时,它们就会消失。这里要注意的重要一点是来自同一范围的上下文变量存在于相同的结构中。让我用一个示例代码来说明它:
function outer () {
var x; // real local variable
var y; // context variable, referenced by inner1
var z; // context variable, referenced by inner2
function inner1 () {
// references context
use(y);
}
function inner2 () {
// references context
use(z);
}
function inner3 () { /* I am empty but I still capture context implicitly */ }
return [inner1, inner2, inner3];
}
在此示例中,变量x
将在outer
返回时消失,但变量只有在两者y
都消失时才会消失,并且死亡。发生这种情况是因为and被分配在同一个上下文结构中,并且所有三个闭包都隐式引用了这个上下文结构(即使它没有显式使用它)。z
inner1
inner2
inner3
y
z
inner3
当您开始使用with -statement时,情况会变得更加复杂, try/catch -statement 在 V8 上包含一个隐式with -statement inside catch 子句或 global eval
。
function complication () {
var x; // context variable
function inner () { /* I am empty but I still capture context implicitly */ }
try { } catch (e) { /* contains implicit with-statement */ }
return inner;
}
在这个例子x
中,只有在死亡时才会消失inner
。因为:
- try/catch - 在 catch 子句中包含隐含的 with - 语句
- V8 假定任何带有-statement的内容都会影响所有本地人
这迫使x
成为一个上下文变量并inner
捕获上下文,因此x
存在直到inner
死亡。
通常,如果您想确保给定变量不会保留某个对象的时间超过实际需要的时间,您可以通过分配给该变量来轻松破坏此链接。null