我正在阅读面向 Web 开发人员的专业 JavaScript
我在阅读“当垃圾收集器运行时,它会标记存储在内存中的所有变量。然后它会清除上下文中的变量和上下文变量引用的变量的标记。”
我知道当任何变量都无法到达对象时,相关的内存将被回收。
“上下文中的变量”是什么意思?它们是可以在作用域链中找到的变量吗?但是“上下文变量引用的变量”呢?
我很困惑。
我正在阅读面向 Web 开发人员的专业 JavaScript
我在阅读“当垃圾收集器运行时,它会标记存储在内存中的所有变量。然后它会清除上下文中的变量和上下文变量引用的变量的标记。”
我知道当任何变量都无法到达对象时,相关的内存将被回收。
“上下文中的变量”是什么意思?它们是可以在作用域链中找到的变量吗?但是“上下文变量引用的变量”呢?
我很困惑。
我假设这是为了避免意外删除闭包中使用的变量。在 javascript 中,就像任何其他函数式语言一样,仅仅无法访问并不足以告诉您天气应该删除一个对象。
以下面的代码为例:
function a () {
var x=0;
return function () {
alert(x++);
}
}
var b = a();
// at this point, the instance of `x` created by calling `a` is
// no longer reachable but we are still using it in the closure.
如果我们只遵循“不可达”规则,那么创建的闭包将丢失变量x
。
考虑一下:
(function(){
var sobriety = [];
window.inception = function() {
var i = 0,
j = 0,
inner_level = { i: i },
level = { level: inner_level },
food = {};
return function() {
var new_level = {
level: level.level
};
new_level[i] = 'step ' + i;
new_level.level.i = i;
sobriety[i++] = new_level;
};
};
window.show_my_sobriety = function() { console.log(sobriety); };
})();
var agent = inception();
agent(); agent(); agent();
show_my_sobriety();
我承认这个例子有些复杂,但我只需要让它显示i
(原始)和inner_level
(引用类型)之间的区别。
这里我们有一个带有一个sobriety
局部变量的模块,以及两个全局函数(通过将它们分配给window
对象的属性)。sobriety
请注意,即使在定义了变量的模块完成( )之后,这些全局函数也可以访问变量in-context
。
inception
函数在调用时定义了五个变量:两个标量(i
和j
)和三个引用(inner_level
、level
和food
),然后定义一个函数并返回它。
这个函数显然访问i
and level
(相同的上下文)和sobriety
(外层上下文) - 但不是j
and food
。因此后者将在window.inception
完成后由 GC 收集;但是,前者没有被收集——因为它们是由内部函数引用的。
现在是棘手的部分。虽然您inner_level
在此函数中看不到访问权限,但它仍然可以访问 - 因为它是level
同名对象的属性值。而且,当您检查结果时,您会看到所有三个元素都具有相同的level.i
值 - 等于 2。这就是“由上下文变量引用的变量”所理解的。