Javascript对象构造:有什么区别?

时间:2011-09-20 17:00:11

标签: javascript oop

这两个对象的构造有什么不同 - 除了成员变量的隐私?

function A() { this.a = 99; }
A.prototype.setA = function(newVal) { this.a = newVal; }
A.prototype.getA = function({ return this.a; }

而且:

function A() {
   var a = 99;
   return {
      setA: function(newVal) { a=newVal; }
      getA: function() { return a; }
   }
}

我对成员变量的隐私不感兴趣,就像定义函数的方式一样。

我是否正确地认为在第二个版本中,通过新A()创建的所有对象都将获得已定义函数的副本,而在第一个版本中,对定义函数的所有调用都将转到一个且只有原型对象(对于A对象)。这是正确的吗?

如果版本2有任何性能成本吗?

此外,有一种方式优于另一种方式 - 还是有更好的方法呢?

非常感谢

4 个答案:

答案 0 :(得分:6)

  

我是否正确地认为在第二个版本中创建了所有对象   通过new A()将获得已定义函数的副本,如中所示   第一个版本对所定义函数的所有调用都将转到一个   并且只有原型对象(对于A对象)。这是对的吗?

  

如果版本2有任何性能成本吗?

使用setA和getA每个对象A的内存使用量更多

  

此外,一种方式优于另一种方式 - 或者是否有更好的方法   再次?

由于您不关心封装,请使用原型

答案 1 :(得分:2)

第一种方法将这些函数定义为A.prototype对象的属性,这意味着这些函数在{strong>一个地方中为A的所有实例定义。

第二种方法直接在实例对象上定义函数(作为属性),这意味着您将为您创建的每个实例创建一组新函数(=更高的内存消耗)。 / p>

第一种方法的优点是,如果需要,您可以隐藏继承的方法

A.prototype.foo = function () { ... };

var a = new A;
a.foo(); // inherited
a.foo = function () { ... };
a.foo(); // shadowed
delete a.foo;
a.foo(); // back to inherited

使用第二种方法时不能这样做。

第二种方法的优点是函数捕获构造函数的上下文,因此您可以在构造函数中使用私有变量和函数,然后函数可以使用它们。

使用原型上定义的函数无法做到这一点。


所以我的建议是: 如果需要私有变量或函数,请使用第二种方法。否则,请使用原型。

答案 2 :(得分:1)

除了内部变量的隐私,这些应该表现得相似,但你是对的,第二个版本将使用比第一个更多的内存。除非你使用大量的对象,否则这通常是微不足道的,但是使用原型方法只有一个getA和setA函数,而第二种方法每个都有自己的函数用于这些方法。

答案 3 :(得分:1)

两个帐户都是正确的。

因此性能差异将是内存消耗 - 第二种方式会消耗更多的每个对象。此外,在第二个版本中,每个对象创建/实例化可能需要稍微长一点,因为您必须创建那些消耗内存的函数,尽管这可以忽略不计(在这个玩具案例中),甚至可能被依赖于实现的因素所抵消。 / p>

我会推荐使用原型方法,因为由于这些原因,它会稍微好一些。关于可见性,即使可以使用ES5以原型方式伪实现。