在构造函数中定义函数会比将其附加到原型消耗更多内存吗?

时间:2012-08-14 08:16:12

标签: javascript google-chrome prototype

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

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

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

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

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

我是否理解正确?

作为奖励问题:在案例B中执行此操作时,chrome开发人员会为doSomething提供intellisense,但我必须扩展__proto__以查看实例。为什么它不会出现在物体本身上?也就是说,为什么原型成员不会在对象上显示,而是被卡在__proto__上?如果__proto__堆栈会变平并直接显示在对象上,我会更喜欢。还有另一个案例会允许这种情况发生吗?

2 个答案:

答案 0 :(得分: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

最后一行是false,因为该方法是继承的,不属于实例。使用模式B,这将解析为真。

答案 1 :(得分:2)

  1. 正确:在原型中定义方法将创建1个函数对象,每个实例将引用该1个函数。在构造函数中定义它会为每个实例创建一个新函数

  2. 您的代码需要一些工作。您定义构造函数的方式是,doSomething函数被定义为作为全局添加var来对付它。这仍然没有将doSomething设置为属性,它只是在构造函数(闭包)范围内声明的函数。这就是为什么它不会在你的实例中显示为一个方法:该函数没有附加到this,但即使修复这个问题,你仍然会为每个实例创建新的函数对象: / p>


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

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

    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
        }
    }