JavaScript:将原型函数放在何处

JavaScript:将原型函数放在何处,javascript,prototype,Javascript,Prototype,我想知道这两种方法的区别是什么。它们都有效,但我不明白第二种方法是否有不良影响 // A. Putting a prototype method outside the function declaration (what I would normally do) var Cat = function(){ } Cat.prototype.eat = function(){ // implementation } // B. Putting a prototype method in

我想知道这两种方法的区别是什么。它们都有效,但我不明白第二种方法是否有不良影响

// A. Putting a prototype method outside the function declaration (what I would normally do)
var Cat = function(){
}

Cat.prototype.eat = function(){
    // implementation
}

// B. Putting a prototype method inside the function declaration (it works too but the scoping seems different)
var Cat = function(){

    Cat.prototype.eat = function(){
        // implementation
    }   
}

你可能想做第一个例子。虽然从技术上讲,第二个函数可以访问Cat的“私有”变量,但它们都在做完全相同的事情。但是,如果您想这样做,正确的方法是使用
this

var Cat = function(){
    var a = 'hi';

    this.eat = function() {
        alert(a); // Exists!
    }
}

请记住,对于上面的示例或原始的“B”示例,eat函数将不存在,除非您使用
new Cat()
实例化一个新的Cat。也就是说,如果您只想对函数本身调用
Cat.eat()
,就像一个实用方法一样,那么使用
prototype
的第一个示例就是正确的选择。

每个对象都有一个原型。原型继承允许您指定一个全新的原型(类似于经典继承):

或者直接向当前类的原型添加变量和方法:

function Cat() {
    // Implementation
}
Cat.prototype.numLegs = 4;

var kitten = new Cat();
console.log(kitten.numLegs); // 4
第二个示例只是在每次启动
Cat
类时将
eat
函数重新分配给Cat原型,这是无用的,但不会占用任何内存,因为它只会覆盖旧值

这为什么有用?记住,函数是对象。对于类的每个实例,该类中定义的每个变量和函数都会占用自己的内存。使用原型继承,您可以共享公共方法,因此不会占用每个实例的额外内存

为什么这没有那么有用?您没有访问私有变量的权限

请记住,这与静态方法不同,静态方法可以声明为:

Cat.feed = function(kittens) {
    for (var kitten in kittens) {
        kitten.eat();
    }
};

第二个例子也会在创建几个<代码> CAT/CODE> s时混乱不堪,因为它们所有的<代码>吃< /代码>方法将访问最后的<代码> CAT/COM>的“私有”变量。哈哈,我甚至没有考虑过。这将导致一些致命的调试。@Vatev-您不能在声明“私有”变量的函数之外访问它们。使用
this
声明的变量是公共的,可以在构造函数和原型方法中访问,因为
this.var
@Wex“private”在这种情况下是
eat
函数通过闭包访问的变量。要使用它,您需要为每只
(如Andy的回答中所示)提供一个单独的
eat
函数实例,但OP的第二个示例为所有猫使用一个实例(每次都用最后一只
猫的eat替换)。谢谢您的评论。我现在还记得为什么我一开始就搞砸了:我找不到从原型函数访问私有变量的方法。我现在明白了,你不应该这么做,因为私有变量只能从创建它们的范围中访问。如果需要访问原型中的变量,则应使用'this'关键字而不是'var'将其声明为公共变量
Cat.feed = function(kittens) {
    for (var kitten in kittens) {
        kitten.eat();
    }
};