这两个对象的构造有什么不同 - 除了成员变量的隐私?
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有任何性能成本吗?
此外,有一种方式优于另一种方式 - 还是有更好的方法呢?
非常感谢
答案 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以原型方式伪实现。