对象成员上的Javascript闭包内存使用情况
我肯定以前有人问过这个问题,但我找不到 以下示例Javascript闭包的内存使用情况是什么:对象成员上的Javascript闭包内存使用情况,javascript,object,closures,Javascript,Object,Closures,我肯定以前有人问过这个问题,但我找不到 以下示例Javascript闭包的内存使用情况是什么: var f = (function(sz){ var obj = { x : sz, y : new Array(sz), }; var _x = obj.x; return function() { return obj.x; }; })(1000000); 对于最终的关闭,应该保留多少obj?是将所有的o
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
保存在内存中
我应该说,我尝试(像一个新手)在谷歌浏览器中使用堆分析器。在关闭之前,总堆大小为5.3MB。关闭后,当我将obj.y
数组大小(sz)设置为1000000时,总堆大小为13.2MB,而f
保留8MB。这表明obj.y
仍保留在内存中。当我将sz
更改为10000000时,堆大小为81.9MB,f
保持了一个健康的80MB。与剩余的obj.y
一致。但是当我使用100000000的sz
时,配置文件显示的堆大小只有5.6M,而f
保留0.5MB。这告诉我,obj.y
与垃圾一起被取出。在任何时候,f()
都会返回正确的值,因此可以推测,闭包按预期工作
因此,问题仍然存在,对于上述结束,记忆中保存着什么?显然,我知道它可以是什么,但它应该是什么?我认为您可以通过在调试器中的
return obj.x行上放置断点来判断闭包中是否包含完整对象代码>,然后添加一行以执行f持有的函数以触发它:
f()代码>
在该断点处,您可以查询对象obj
,您将看到它实际上是整个对象。所以我想说,是的,所有的obj都是基于这一点被关闭的
我使用node和Chrome浏览器对此进行了测试,得到了相同的结果。也许其他javascript引擎对此进行了优化,并表现出不同的行为
关于垃圾收集,我想说,衡量垃圾收集器的工作是一项挑战,因为这种情况何时发生是相当不可预测的,并且取决于很多因素
编辑-其他信息
我想更清楚地说明这次关闭的原因。在JavaScript中,垃圾收集只会发生在不可访问的对象(变量、函数等)上。只要某些东西是可以到达的,它就不会被垃圾收集
要查看此函数包含的闭包,我们可以在控制台中使用console.dir()
命令
以下是控制台会话示例(Chrome浏览器控制台):
var f=(函数(sz){
var obj={
x:sz,
y:新阵列(sz),
};
var_x=对象x;
返回函数(){
返回obj.x;
};
})(1000000);
控制台目录(f)
函数匿名()
参数:null
呼叫方:空
长度:0
姓名:“
原型:对象
__原型:()
[[FunctionLocation]]:VM24461:9
[[Scopes]]:作用域[2]
0:结束
对象:对象
x:1000000
y:数组[1000000]
__原型:对象
1:全球
我认为您可以通过在调试器的return obj.x行中放置一个断点来判断闭包中是否包含完整对象代码>,然后添加一行以执行f持有的函数以触发它:
f()代码>
在该断点处,您可以查询对象obj
,您将看到它实际上是整个对象。所以我想说,是的,所有的obj都是基于这一点被关闭的
我使用node和Chrome浏览器对此进行了测试,得到了相同的结果。也许其他javascript引擎对此进行了优化,并表现出不同的行为
关于垃圾收集,我想说,衡量垃圾收集器的工作是一项挑战,因为这种情况何时发生是相当不可预测的,并且取决于很多因素
编辑-其他信息
我想更清楚地说明这次关闭的原因。在JavaScript中,垃圾收集只会发生在不可访问的对象(变量、函数等)上。只要某些东西是可以到达的,它就不会被垃圾收集
要查看此函数包含的闭包,我们可以在控制台中使用console.dir()
命令
以下是控制台会话示例(Chrome浏览器控制台):
var f=(函数(sz){
var obj={
x:sz,
y:新阵列(sz),
};
var_x=对象x;
返回函数(){
返回obj.x;
};
})(1000000);
控制台目录(f)
函数匿名()
参数:null
呼叫方:空
长度:0
姓名:“
原型:对象
__原型:()
[[FunctionLocation]]:VM24461:9
[[Scopes]]:作用域[2]
0:结束
对象:对象
x:1000000
y:数组[1000000]
__原型:对象
1:全球
需要注意的一点是,newarray(n)
不(一定)占用太多内存,因为数组是用“空槽”创建的-请尝试newarray(sz)。fill(“”)
要查看差异,闭包的垃圾收集是,但不是每个对象属性。它需要对对象的使用进行大量的假设。需要注意的是,newarray(n)
不(一定)占用太多内存,因为数组是用“空槽”创建的-请尝试newarray(sz)。fill(“”)
要查看差异,闭包的垃圾收集是,但不是每个对象属性。它需要对对象的用法进行大量假设。我认为你是对的。如果尝试了调试器(也像新手一样),并观察到了相同的情况。但是当我用return\ux
替换时,obj
不再可见。我想你是对的。如果尝试了调试器(也像新手一样),并观察到了相同的情况。但是当我用return\ux
替换时,obj
不再可见。
> 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