JavaScript类内存使用情况

JavaScript类内存使用情况,javascript,class,v8,spidermonkey,Javascript,Class,V8,Spidermonkey,所以我一直在做一些JavaScript类的东西,比如 MyClass = function() { var x; this.sayX = function() { alert(x); } } 但我也看到了 MyClass = function() { this.x = 0; } MyClass.prototype.sayX = function() { alert(this.x); } 最大的问题是,我是否仍然在浪费今天JavaScript

所以我一直在做一些JavaScript类的东西,比如

MyClass = function()
{
   var x;

   this.sayX = function()
   {
      alert(x);
   }
}
但我也看到了

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

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

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

第一个的内存占用总是更大。考虑<代码>原型< /Cord>作为所有实例都可以使用的方法的共享包。它之所以有效,是因为您没有为每个实例创建新函数,而是重用了内存中已有的方法

好消息是你展示的两种方式可以结合起来

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);
     },
     // ...
   };
})();

稍后会大量地重新讨论这个问题,但事实证明V8足够聪明,它不会在第一个方法中创建该函数的多个实例。转到隐藏类:D


请注意,如果有帮助,可以使用。不要使用“with”。它使用起来很危险,将从ECAMScript的未来实现中删除。这一点再怎么强调也不为过——最好假装JavaScript中不存在“with”。如果您使用第一种方法,如果您使用任何继承,那么您需要更加小心您的操作、如何混合这两种技术、何时调用超级构造函数等。这并不是严格意义上的正确(“第一个的内存占用空间将始终更大”)。假设一次只存在一个上述类型的对象。尽管你可能会认为第一个实例绑定了另一个执行上下文…但这更准确:-)你的评论几乎没有建设性。如果他只需要一个对象实例,他会创建一个单例,而不担心内存占用。这就是它的信息量很大,但实际上根本不能回答我的问题。现代JavaScript引擎可以优化这一开销吗?我可能只是构建一些测试来找出答案。第一句话回答了你的问题。你展示的两个代码不完全相同,因为它们具有不同的作用域链,因此无法优化。我已经用第三种模式允许您使用数据隐藏,它使用共享功能(较小的内存占用)演示:应该注意的是,第三种模式可以说是非惯用的,因为它需要使用
new
关键字,并且每个实例都是唯一的,但是所有实例共享相同的状态。在某些方面,它们类似于实例,而在其他方面类似于单例。执行
five=new MyClass(5);seven=新的MyClass(7);five.sayX();
生成“7”。