对象成员上的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

我肯定以前有人问过这个问题,但我找不到

以下示例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
保存在内存中

我应该说,我尝试(像一个新手)在谷歌浏览器中使用堆分析器。在关闭之前,总堆大小为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