【问题标题】:JavaScript class memory usageJavaScript 类内存使用情况
【发布时间】:2010-11-07 06:55:30
【问题描述】:

所以我一直在做一些类似于 JavaScript 的类的东西,例如

MyClass = function()
{
   var x;

   this.sayX = function()
   {
      alert(x);
   }
}

但我也见过

MyClass = function()
{
   this.x = 0;
}

MyClass.prototype.sayX = function()
{
   alert(this.x);
}

最大的问题是,我是否还在今天的 JavaScript 引擎中浪费内存空间,还是他们能够看到我的方法中的重复并优化它们?我问的原因是因为我宁愿进行适当的数据隐藏,而不必在所有内容前加上“this”。

【问题讨论】:

  • 请注意,如果对您有帮助,您可以使用with(this) { }
  • 不要使用“with”。它使用起来很危险,并且将从 ECAMScript 的未来实现中删除。不能强调这一点 - 最好假装 JavaScript 中不存在“with”。
  • 如果你用第一种方法,如果你做任何继承,你需要更加小心你做什么,你如何混合这两种技术,当你调用超级构造函数时,等

标签: javascript class v8 spidermonkey


【解决方案1】:

第一个的内存占用总是更大。将prototype 视为所有实例都可以使用的共享方法包。它之所以有效,是因为您不会为每个实例创建一个新函数,而是重用内存中已有的方法。

好消息是您展示的两种方式可以结合使用。

MyClass = function () {
   var x;
   // public method with access 
   // to private variables
   this.sayX = function () {
      alert(x);
   };
}
// method that doesn't need access to private variables
MyClass.prototype.sharedMethod = function () {
   // ...
}

但就您处理小型代码库而言,您不必担心内存使用情况。你甚至可以使用像

这样的模式
// everything will be created for every
// instance, but the whole thing is nicely
// wrapped into one 'factory' function
myClass = function () {
   // private variables
   var x;

   // private methods
   function doSomethingWithX() {}

   // public interface
   return {
     sayX: function () {
       alert(x);
     },
     publicMethod: function () { .. },
     // ...
   };
};

注意,我特意把 myClass 改成了小写,因为它不再是构造函数,调用时不需要使用new


更新 - 第三种模式非常适合您的需求:

MyClass = function (x, y, whatever) {
   this._init.apply(this, arguments);
}

// The prototype creates a scope for data hiding.
// It also includes a constructor function.
MyClass.prototype = (function () {
   var x; // private
   return {
     _init: function (x_in) {
       x = x_in;
     },
     sayX: function () {
       alert(x);
     },
     // ...
   };
})();

【讨论】:

  • 严格来说这不是真的(“第一个的内存占用总是更大”)。想象一下,一次只存在一个上述类型的对象。虽然那时你可能会争辩说第一个案例有另一个执行上下文绑定......但那更精细:-)
  • 您的评论几乎没有建设性。如果他只需要一个对象的实例,他会创建一个单例并且不用担心内存占用。
  • 这非常有用,但它实际上并没有回答我的问题。现代 JavaScript 引擎可以优化掉这种开销吗?我可能只是建立一些测试来找出答案。
  • 第一句话回答了你的问题。您展示的两个代码并不完全相同,因为它们具有不同的作用域链,因此无法优化。我已经用 第三个模式 更新了答案,它让您可以使用数据隐藏、使用共享函数(内存占用少),并且有一个构造函数。 演示: jsbin.com/osixa4
  • 应该注意的是,第三种模式可以说是非惯用的,因为它需要使用 new 关键字并且每个实例都是唯一的,但是所有实例共享相同的状态。在某些方面,它们就像实例,在其他方面就像单例。执行five = new MyClass(5); seven = new MyClass(7); five.sayX(); 产生“7”。
【解决方案2】:

稍后重温这一点,但事实证明 V8 足够聪明,它不会在第一种方法中创建该函数的多个实例。去隐藏类:D

http://www.youtube.com/watch?v=hWhMKalEicY

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-07-30
    • 1970-01-01
    • 1970-01-01
    • 2011-06-21
    • 1970-01-01
    • 2013-01-14
    • 1970-01-01
    • 2012-01-25
    相关资源
    最近更新 更多