【问题标题】:Javascript private methods -- what is the memory impact?Javascript私有方法——内存影响是什么?
【发布时间】:2010-02-10 19:03:46
【问题描述】:

我正在编写一些代码,试图在闭包中隐藏一些私有变量。问题是环境在内存方面受到了相当大的限制,所以我还关心保持类的整体占用空间较低。

与仅将对象上的所有方法和变量公开相比,使用闭包隐藏私有实例变量和方法有什么影响?使用闭包的实例会比不使用闭包的实例占用更多内存吗?如果是这样,我希望使用多少内存?

我的代码看起来像这样

function Foo() {
   // private variables
   var status = 3;
   var id = 4;
... 
...

   // private methods
   var privateMethod = function () {
      // do something awesome
   }
   ...

   // a whole bunch of these


   // public methods

   this.publicDriver =  function () {
        privateMethod();
   }
    .. a few more of these

};

对比

function Bar() {
   // only define public variables
   this.x = 1;
   this.y = 3;
}

Bar.prototype.method1 = function () { 
// blah;
}

....继续并定义所有其余的方法。

【问题讨论】:

  • 为什么不写一些基准测试并自己找出答案?
  • 我会的,只要我有更多的时间。该代码不是在传统的浏览器设置中运行,而是在设备上运行..所以很多标准工具不可用,或者需要一些调整/学习才能跟上速度。我们没有在代码中使用任何类型的框架……更多我关心的是堆栈帧分配。通过在同一个类中声明多个闭包,我会冒着环境信息冗余副本四处飘荡的风险,还是它们都使用相同的堆栈帧? (也许 js 的术语不合适,但你可能知道我的意思)
  • 另外,我知道我可以在浏览器中使用一些虚拟类对其进行测试,我当然可以尝试在工作之外对其进行基准测试。我只是想知道一个标准的 js 引擎如何在一个类中处理多个相当大的闭包。

标签: javascript memory closures private-members


【解决方案1】:

好的,所以据我所见,使用闭包案例构造类会为构造函数中定义的每个方法构造新的函数对象,而原型分配方式会创建一个由对象的所有实例共享的中心函数。然后为每个对象解释中心实例以获取正确的实例变量引用。

我猜在闭包示例中定义的每个函数都指向同一个堆栈帧。

不过,在我的情况下,漂浮的物体要多得多。

【讨论】:

  • 实际上只是在“高性能 Javascript”一书中读了一点就证实了这一点。
【解决方案2】:

以下链接显示了有关分析 javascript 函数以查看其性能信息的一些提示的信息:

http://ejohn.org/blog/function-call-profiling/

【讨论】:

    【解决方案3】:

    查看these 基准。尽管它们是继承基准,但它应该让您了解内存影响,因为其中一些使用闭包,而另一些则不使用。

    【讨论】:

      【解决方案4】:

      闭包中的变量可以在 JavaScript 中从闭包外部更新,这表明该变量只存在一个副本。这意味着没有理由在 JavaScript 中使用闭包会对内存产生任何重大影响。

      如果在创建闭包后变量的值被冻结,那将是另一回事,因为这意味着每个闭包都必须拥有其封闭变量的私有副本。

      话虽如此,您仍然应该执行实际的基准测试来检查:-)

      【讨论】:

      • 不幸的是,我认为这些 cmets 是不正确的(嗯,除了关于做基准检查的那个 :-)。 “闭包”变量保留在函数的 调用 的堆栈框架中,并且只能由在同一调用中创建的函数操作,并且以某种方式在关闭。在 Gopherkhan 的 Foo() 构造函数中,如果他调用 "f1 = new Foo(); f2 = new Foo()" 并且 Foo 定义了可以修改和访问 "status" 闭包变量的方法,他将能够看到两个对象之间的值不同。
      • 我觉得你误会了我。考虑一下:function Baz() {var p = 42; this.setP = function(q) {p=q;};this.getP = function(){return p;}}。在某些语言中,getP() 将始终返回 42,即使 setP 已用另一个值调用。这是因为 getP 在创建时会复制 p 的副本,并且当 p 在外部范围内更新时,该副本不会被更新。但在 JavaScript 中情况并非如此:getP 中的 p 与 setP 中的 p 引用相同,因此可以更新。
      猜你喜欢
      • 2013-05-21
      • 1970-01-01
      • 2011-01-16
      • 2017-07-07
      • 2011-03-07
      • 1970-01-01
      • 2020-11-24
      • 1970-01-01
      • 2020-05-14
      相关资源
      最近更新 更多