Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/395.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 在构造函数中定义函数会比将其附加到原型中消耗更多内存吗?_Javascript_Google Chrome_Prototype - Fatal编程技术网

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

Javascript 在构造函数中定义函数会比将其附加到原型中消耗更多内存吗?,javascript,google-chrome,prototype,Javascript,Google Chrome,Prototype,这可能是最安全的方式(案例A): 这是备选方案(案例B): 我的印象是,如案例B所示,通过这样做,doSomething将成为一个成员,并且该函数将为我实例化的每个myClass对象定义一次,这样它将在内存中100次存在100个实例,而在案例A中,函数只存在于内存中的一个位置,不同的实例只会引用原型 我理解正确吗? 作为一个额外的问题:当像案例B那样做时,chrome developer为我提供了有关doSomething的intellisense,但我必须展开“proto”以获得一个实例来查看

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

这是备选方案(案例B):

我的印象是,如案例B所示,通过这样做,doSomething将成为一个成员,并且该函数将为我实例化的每个myClass对象定义一次,这样它将在内存中100次存在100个实例,而在案例A中,函数只存在于内存中的一个位置,不同的实例只会引用原型

我理解正确吗?


作为一个额外的问题:当像案例B那样做时,chrome developer为我提供了有关doSomething的intellisense,但我必须展开“proto”以获得一个实例来查看它。为什么它不出现在物体上?也就是说,为什么原型成员不显示在对象上,而被困在原型上?如果_uproto _;堆栈被展平并直接显示在对象上,我会更愿意这样做。还有其他情况允许这种情况发生吗?

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

this.doSomething = function() { }
第二,第一个会更快。尽管我现在找不到链接,jQuery honcho John Resig对此做了一篇详细的博客文章,展示了方法的原型继承与实例上声明的方法的速度测试。遗传速度明显加快

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

如果这是你喜欢模式B的原因,那么在继承方法的同时也可以这样做;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,这将解析为true

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

  • 您的代码需要一些工作。按照定义构造函数的方式,
    doSomething
    函数被定义为一个全局的add
    var
    ,以应对这种情况。不过,这仍然没有将
    doSomething
    设置为属性,它只是在构造函数(闭包)范围内声明的函数。这就是为什么它没有作为一种方法出现在您的实例中:函数没有附加到
    This
    ,但是即使这样解决了这个问题,您仍然为每个实例创建新的函数对象:


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

    案例B应该是
    this.doSomething=…
    ,但是是的,它会为每个实例创建一个单独的函数。有人回答这个额外的问题吗?:)@米通:显然,Chrome开发者的决定是正确地反映原型链,而不是将其扁平化。该属性不会显示在对象中,因为该对象实际上没有该属性(请尝试
    obj.hasOwnProperty('doSomething')
    )。查看实际的链对于调试来说更好,因为您可以看到哪个属性可能会隐藏另一个属性。这回答了你的问题吗?事实上我更喜欢案例B,因为我非常确信它会像我描述的那样工作,并且已经得到证实。然而,一位同事认为我不对,因此提出了这个问题。=)您添加的模式C是一个很好的变体,但是我不喜欢添加额外的不必要的条件,即使在几乎所有情况下减速都可以忽略不计。hasOwnProperty对我来说是一个很好的额外信息。B类可以,但速度会慢一些,这违反了原型继承的原则——原型是可重用功能的场所,而不是实例本身。祝你好运。。很抱歉我把哪个案子和哪个案子搞混了。我刚才说的没有道理。我指的是案例A,因为这是一个继承有效的案例。无论如何谢谢。你为什么喜欢函数MyConstructor(){}而不喜欢var MyConstructor=function(){}?事实上,是的:我使用
    var someF=function(){}
    来区分构造函数和常规函数。老实说,我几乎只在闭包中使用
    var someF=
    ,我知道我应该更经常地使用
    var myFunc(){}
    ,但我想旧习惯很难改掉。。。虽然这个问题问得很好,但我在输入答案时并没有认真考虑。。我想我会把它作为一项政策来采用也许不是。似乎当我有一个名称空间的类时,我不能这样做。@Mithon:我甚至不能说我的习惯应该被视为是良好的实践,至少从定义上来说不是这样-P、 但是,当我使用构造函数时,这种风格让我清楚了区别(我不再经常使用它们了。我有一个youtube Crockford OD,每次我键入
    new
    时,我都会看到他的胡子,并听到一个提示,
    new
    在90%的情况下可以避免)
     function SomeClass(name) {}
     SomeClass.prototype.someMethod = function() {};
     var instance = new SomeClass();
     console.log(!!instance.someMethod); //true
     console.log(instance.hasOwnProperty('someMethod')); //false
    
     function MyConstructor()//capitalize constructors - conventions are important
     {
         var someMethod = function(){/*..*/};
         this.someMethod = someMethod;
     }
    
    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
        }
    }