在JavaScript中使用原型有什么实际优势吗?

在JavaScript中使用原型有什么实际优势吗?,javascript,inheritance,function,prototype,Javascript,Inheritance,Function,Prototype,我刚刚完成了Doug Crockford的,他提供了三种不同的继承方法:经典模型的继承、基于原型的继承和功能继承 在后者中,他创建了一个函数,一个排序工厂,它吐出对象,并在其他对象的基础上添加所需的方法;大致如下: var dog = function(params) { // animal is the 'super class' created // the same way as the dog, and defines some // common methods

我刚刚完成了Doug Crockford的,他提供了三种不同的继承方法:经典模型的继承、基于原型的继承和功能继承

在后者中,他创建了一个函数,一个排序工厂,它吐出对象,并在其他对象的基础上添加所需的方法;大致如下:

var dog = function(params) {
    // animal is the 'super class' created
    // the same way as the dog, and defines some
    // common methods
    var that = animal(params);
    that.sound = 'bark';
    that.name = function () {};
    return that;
}
由于以这种方式创建的所有对象都将引用相同的函数,因此内存占用将比使用
new
操作符时低得多。问题是,在这种情况下,原型方法是否有任何优势?换句话说,对象原型是否以某种方式“更接近金属”,从而提供性能优势,或者它们只是一种方便的机制

编辑:我将简化这个问题。原型与通过对象组合进行的仿真。只要您不要求所有对象实例都使用新方法进行更新(这只是原型提供的便利),那么首先使用原型有什么好处吗

我给Doug Crockford发了电子邮件,他说:

[使用上述功能方法与原型相比]没有那么多内存。如果您有大量的对象乘以大量的方法,那么您可能希望使用原型。但如今记忆丰富,只有极端的应用才会注意到它

原型可以使用更少的内存,但检索速度可能稍慢,特别是当链很长时。但一般来说,这并不明显


这些实例并不都引用相同的函数等。每次调用“dog”都会创建一个新的“name”函数实例。

对此有很多看法,Crockford的未必正确

修改原型的主要缺点是,它可能会使使用其他javascript库变得更加困难

但是Crockford创建类的函数式方法的缺点是,您不能像在类型的所有实例中那样轻松地添加方法或字段

有关Crockford关于javascript中类和继承的观点的一些评论,请参见Close:The Financial Guide:


像Dojo、GoogleClosure库(它似乎复制了Dojo的风格)这样的库,也许YUI有自己的类系统,这似乎是一个很好的折衷方案。我最喜欢Dojo的系统,因为它支持mixin,而不是闭包。其他一些与gui工具包无关的类系统包括Joose、JS.class和JavascriptMVC(请查看最后一个,特别是使用jquery时)。

我曾经创建了一个gui,该gui由一个类支持,该类对所需信息没有很好的基于事件的支持。GUI实现了一个通用接口,其中传入了该类的实例,因此我无法从该类继承,所以我做了一些类似于基于原型的继承的事情,我创建了一个代理对象,当该类的实例传递到我的GUI时,它会包装该类的实例。代理截取改变状态的感兴趣的方法,并将它们报告为事件。然后,整个GUI围绕使用这些事件展开

在这种情况下,创建一个单独的类来包装传入的实例并复制相同的接口会很烦人。由于创建了所有冗余函数,这实际上会导致更多的开销(这并不重要)

根本没有其他可行的选择。唯一的选择是:

  • 创建一个组成传递给GUI的对象的对象(如我上面提到的)。然后,这个对象将复制原始类中的每个函数来实现相同的接口,并添加事件,因此它实际上与代理对象的方式相同
  • 让GUI跟踪其传入对象中的状态变化。这将是一个痛苦和错误倾向

  • 嗯,你说得对,不知怎么的,我没看到。那不是很可怕吗?:)问题是:与简单地从多个对象中引用相同的函数相比,原型有什么优势吗?每个实例没有单独的实用函数副本,这样可以节省大量内存。@mitjak:我不知道是否有JS实现可以做到这一点,但在这种情况下,有些语言可以做到(透明地)创建一个在
    dog
    内部创建的函数的静态实例,每次调用
    dog
    时,它只会为该函数提供一个新的引用。如果每个函数都必须具有不同的标识,则每次都可能生成此函数,但可能会有很小的开销,但生成的每个函数将引用相同的字节码(可能还有不同的闭包)。在任何情况下,开销都可能是微不足道的。@Pointy我的代码是一个糟糕的例子。假设引用得到了正确维护,因此每个实例都引用了相同的“核心”对象。那么呢?我感兴趣的是原型是否提供了任何性能优势,因为它们的行为可以在一定程度上被模拟。Thanks对这些建议表示感谢,但有一个问题是:“修改原型的主要缺点是它可能会使使用其他javascript库变得更加困难。”为什么我要修改内置对象的原型?我主要谈论的是我自己创建的对象的原型。@mitjak修改内置对象的原型有点流行;例如,请参阅Prototype library,它可以尽情地进行修改。它很流行,但这不正是我在这里想要了解的。