Javascript 不将一个函数声明为另一个自定义函数的原型的用例?

Javascript 不将一个函数声明为另一个自定义函数的原型的用例?,javascript,jquery,object,prototype,Javascript,Jquery,Object,Prototype,我正试图找到在现有自定义对象中声明js函数的正确方法 例如,通常我这样做是为了向现有对象添加函数: 以下方法的优点是什么 function whateverController() { ...some random code } whateverController.prototype.doSomething = function() { } 从我所阅读的内容来看,后一个示例是声明这些函数的最佳方式,以避免每次创建新的whateverController对象时都必须重新创建这些

我正试图找到在现有自定义对象中声明js函数的正确方法

例如,通常我这样做是为了向现有对象添加函数:

以下方法的优点是什么

function whateverController() {
    ...some random code
} 

whateverController.prototype.doSomething = function() { 

}
从我所阅读的内容来看,后一个示例是声明这些函数的最佳方式,以避免每次创建新的whateverController对象时都必须重新创建这些函数

有人能提供一个好的用例吗?我的前一个例子在哪里更合适?如果有的话?任何好的阅读链接都会很有帮助


后一种方法被认为是标准的吗?

首先,这里的区别只有在您不只是创建单例时才真正重要——或者换句话说,除非您创建一个类的多个实例,否则所有这些都不重要,例如:

var redController = new whateverController();
var blueController = new whateverController();
现在,如果您要创建一个对象的多个实例,那么就应该尽可能多地使用该类的原型。原因很简单。如果我们这样做:

function whateverController() {
    this.doSomething = function() {
        // TODO - do stuff
    }
}

var redController = new whateverController();
var blueController = new whateverController();
var greenController = new whateverController();

redController.doSomething(); // Works fine!
blueController.doSomething(); // Yup, this too!
greenController.doSomething(); // Looking good!
它会起作用,但要付出代价:每个
新的whateverController()
都会创建自己的
doSomething
。换句话说,您现在有三个完全独立的
doSomething
函数

想象一下,如果这个类有十几个函数,而您创建了几十个实例?它很快就失控了

这就是原型版本的用武之地。如果我们将代码更改为:

function whateverController() {
    // ...some random code
} 

whateverController.prototype.doSomething = function() { 
    // TODO - do stuff
}

var redController = new whateverController();
var blueController = new whateverController();
var greenController = new whateverController();

redController.doSomething(); // Alright!
blueController.doSomething(); // Still good!
greenController.doSomething(); // ...you get the idea ;)
现在,每个控制器不再拥有自己的
doSomething
,而是使用原型的
doSomething
;他们并不是每次都创建一个新函数!现在,如果你有一个包含12个函数的类,你可以创建该类的1000个实例,而你在内存中仍然只有原来的12个函数。效率要高得多

现在,您可能希望使用第一个版本而不是原型版本。当你想这样做的时候,简短的版本非常简单:任何时候你绝对需要一个对象有它自己特定的函数版本。通常你不会遇到这种情况,但是如果你开始在JavaScript中使用“私有”变量,你会发现你很快就开始需要它们了

尽管如此,请记住,只有当您计划创建一个对象的多个实例时,这才真正重要。如果只有一个
whateverController
,并且永远只有一个,那么您可以选择更适合您的版本。毕竟,如果您没有创建类的新实例,那么您也不会创建函数的新实例


哦,在我忘记之前还有一个想法:一般认为类构造函数以大写字母开头。换句话说,如果您不打算将
whateverController
作为一个单例使用,并且希望使用它来创建类的实例,那么您可能应该将其命名为
whateverController

它的一个有用之处是模拟私有方法和成员

JavaScript没有提供指定可见性的方法,但有一种通过使用闭包进行欺骗的方法运行函数时,它的变量存在于一个闭包中,只要有任何对象引用它,它就存在于闭包中,但闭包之外的任何对象都看不到它们,除非将它们附加到位于闭包之外的对象上。您的代码没有显示它,但您可以执行以下操作:

function whateverController() {
    // START OF SCOPE
    var privateMember = "secret"; // this acts like a private member.

    function privateMethod() {
        // This function is private.
        // Only other functions declared inside this call can see it.
        // But it can see privateMember, and other private stuff, just fine.
    }
    this.doSomethingPublic = function() {
        // This function is public and privileged.
        // It can see privateMember and privateMethod, and outside functions can see it.
        // This is because you attached it to "this".
    }
    // END OF SCOPE
}
whateverController.prototype.doSomethingElse = function() {
    // This method is public but not privileged.
    // It cannot see privateMember or privateMethod,
    // because they were declared outside its scope. But it CAN
    // see this.doSomethingPublic, because you attached it to this.
}
这样做的缺点是必须在构造函数中声明私有函数和特权函数。这意味着每次运行构造函数时都会重新创建它们,这对性能不利。但从好的方面来说,他们可以使用这个技巧来创建伪私有的东西,而在原型上声明的东西是做不到的


底线:最好尽可能将函数放在原型上,但有时有很好的理由将它们放入构造函数中。这不是你应该一直做的事情。

这里有一个例子,第一种方法是有用的:在解释差异方面也很有帮助。谢谢接受斯普尼斯特的回答,因为他给出了一个很好的例子,说明了为什么你会用一种方法而不是另一种方法。干杯
function whateverController() {
    // START OF SCOPE
    var privateMember = "secret"; // this acts like a private member.

    function privateMethod() {
        // This function is private.
        // Only other functions declared inside this call can see it.
        // But it can see privateMember, and other private stuff, just fine.
    }
    this.doSomethingPublic = function() {
        // This function is public and privileged.
        // It can see privateMember and privateMethod, and outside functions can see it.
        // This is because you attached it to "this".
    }
    // END OF SCOPE
}
whateverController.prototype.doSomethingElse = function() {
    // This method is public but not privileged.
    // It cannot see privateMember or privateMethod,
    // because they were declared outside its scope. But it CAN
    // see this.doSomethingPublic, because you attached it to this.
}