我确信之前已经问过,但我找不到它。
以下示例Javascript闭包的内存使用情况是什么:
var f = (function(sz){
var obj = {
x : sz,
y : new Array(sz),
};
var _x = obj.x;
return function() {
return obj.x;
};
})(1000000);
应该为结果闭包保留多少obj
?将所有obj
保留在内存中,还是仅保留obj.x
的内容?
我应该说我尝试(像新手一样)在Google Chrome中使用堆分析器。在关闭之前,总堆大小为5.3MB。关闭后,当我将obj.y
数组大小(sz)设置为1,000,000时,总堆大小为13.2MB,f
保留8MB。这表明obj.y
仍留在记忆中。当我将sz
更改为10,000,000时,堆大小为81.9MB,f
保持健康的80MB。与剩余obj.y
一致。但是当我使用100,000 {的sz
时,配置文件显示堆大小仅为5.6M,f
保留0.5MB。这告诉我obj.y
被垃圾带走了。并且在任何时候,f()
都会返回正确的值,因此假设闭包按预期工作。
所以问题仍然存在,上述关闭内存中的内容是什么?显然,我知道它可以是什么,但它应该是什么?
答案 0 :(得分:2)
我认为你可以通过在means/1
行的调试器中放置一个断点来判断闭包中是否包含完整的对象,然后添加一行来执行f所持有的函数来触发它: / p>
return obj.x;
在该断点处,您可以查询对象f();
,您将看到它确实是整个对象。所以我想说,是的,所有的obj都是基于那个闭包。
我使用节点并使用具有相同结果的Chrome浏览器对此进行了测试。也许其他javascript引擎优化了这一点并且表现不同。
关于垃圾收集,我想说对垃圾收集器所做的事情进行测量是很有挑战性的,因为当这种情况发生时是相当不可预测的并且取决于很多因素。
编辑 - 附加信息
我想更清楚地说明闭包的内容。在JavaScript中,垃圾收集只会发生在无法访问的事物(变量,函数......)上。只要有东西可以到达,它就不会被垃圾收集。
要查看此函数包含的闭包,我们可以在控制台中使用obj
命令。
以下是控制台会话示例(Chrome浏览器控制台):
console.dir()
现在,感兴趣的是在> var f = (function(sz){
var obj = {
x : sz,
y : new Array(sz),
};
var _x = obj.x;
return function() {
return obj.x;
};
})(1000000);
<- undefined
> console.dir(f)
function anonymous()
arguments: null
caller: null
length: 0
name: ""
prototype: Object
__proto__: ()
[[FunctionLocation]]: VM24461:9
[[Scopes]]: Scopes[2]
0: Closure
obj: Object
x: 1000000
y: Array[1000000]
__proto__: Object
1: Global
<- undefined
下我们看到这个函数的闭包,并且该闭包是[[Scopes]]
。这意味着obj是可达的,因此不能进行垃圾回收。这也意味着obj.y可以访问(通过obj),因此也不能进行垃圾收集。
希望这有助于进一步明确。 obj
非常便于查看更多关闭。