2

这可能是最安全的方式(案例 A):

var myClass = function() { };
myClass.prototype = {
    doSomething : function() { alert('Something'); }
};

这是替代方案(案例 B):

var myClass = function() {
    this.doSomething = function() { alert('Something'); };
};

我的印象是,通过如案例 B 所示执行此操作,doSomething 将成为一个成员,并且该函数将为我实例化的每个 myClass 对象定义一次,以便它将在 100 个实例的内存中存在 100 次,而在案例 A 函数只存在于内存中的一个地方,不同的实例只会引用原型。

我是否正确理解这一点?

作为一个额外的问题:在案例 B 中执行此操作时,chrome 开发人员为我提供了 doSomething 的智能感知,但我必须扩展 __proto__ 才能看到它。为什么它没有出现在对象本身上?也就是说,为什么原型成员没有显示在对象上,而是被困在 __proto__ 上?如果 __proto__ 堆栈会被展平并直接显示在对象上,我会更喜欢。是否有另一个案例会允许这种情况发生?

4

2 回答 2

4

首先,在情况 B 中,您只是在创建一个全局函数,而不是将其附加到实例。你的意思是:

this.doSomething = function() { }

其次,第一个会更快。虽然我现在找不到链接,但 jQuery honcho John Resig 写了一篇详细的博客文章,展示了方法的原型继承与实例上声明的方法的速度测试。继承明显更快。

在精神方面,我一直非常喜欢继承。这是可重用、跨实例功能的地方。将它添加到每个实例的唯一好处是允许您在构造函数中在一个方便的闭包内声明方法,但仅此而已。

如果这是您喜欢模式 B 的原因,则可以在仍然 a) 继承方法的同时执行此操作;b) 不要在每次实例化时重新声明它们。

function SomeClass() {
    if (!SomeClass.prototype.someMethod) {
        SomeClass.prototype.someMethod = function() {}
    }
}

不过,这会稍微减慢初始实例化速度,因为它负责设置原型 - 而不是实例化过程的真正工作。

在您的两种情况下,还需要注意程序上的差异:

 function SomeClass(name) {}
 SomeClass.prototype.someMethod = function() {};
 var instance = new SomeClass();
 console.log(!!instance.someMethod); //true
 console.log(instance.hasOwnProperty('someMethod')); //false

最后一行是假的,因为该方法是继承的,而不是实例拥有的。使用您的模式 B,这将解决为 true。

于 2012-08-14T08:23:17.800 回答
2
  1. 正确:在原型中定义方法将创建 1 个函数对象,并且每个实例都将引用该 1 个函数。在构造函数中定义它为每个实例创建一个新函数

  2. 您的代码需要一些工作。您定义构造函数的方式,该doSomething函数被定义为一个全局添加var来对抗它。尽管如此,这仍然没有设置doSomething为属性,它只是在构造函数(闭包)范围内声明的函数。这就是为什么它没有作为方法出现在您的实例中的原因:该函数未附加到this,但即使像这样修复此问题,您仍然为每个实例创建新的函数对象:


 function MyConstructor()//capitalize constructors - conventions are important
 {
     var someMethod = function(){/*..*/};
     this.someMethod = someMethod;
 }

Utkanos 指出了继承和原型方法的含义(.hasOwnProperty),他在这方面是绝对正确的(+1)。我只想补充一点,hasOwnProperty返回 false 的方法是一件小事。一般来说,在迭代对象时,检查哪些属性和方法已设置,哪些未设置。在大多数情况下,您想要的是属性,而不是方法。所以实际上最好将它们设置在原型级别:

for(var name in obj)
{
    if (obj.hasOwnProperty(name))
    {
        //do stuff, here the methods are set @ prototype level
    }
    if (obj.hasOwnPrototype(name) && typeof obj[name] !== 'function')
    {
        //same stuff, but requires extra check when methods are assigned by constructor
    }
}
于 2012-08-14T08:24:03.760 回答