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