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

Use case for not declaring a function as a prototype of another custom function?

本文关键字:原型 自定义函数 另一个 函数 声明      更新时间:2023-09-26

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

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

function whateverController() {
    this.doSomething = function() {
    }
}

按照以下方式做有什么好处?

function whateverController() {
    ...some random code
} 
whateverController.prototype.doSomething = function() { 
}

从我读到的内容来看,后一个例子是声明这些函数的最佳方式,以避免每次创建新的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.
}

这样做的缺点是,私有函数和特权函数必须在构造函数内部声明。这意味着每次运行构造函数时都会重新创建它们,这对性能不利。但从好的方面来说,他们可以使用这个技巧来创建伪私有的东西,而在原型上声明的东西是做不到的

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

首先,只有当您不只是创建singleton时,这里的差异才真正重要——换句话说,除非您创建了一个类的多个实例,否则所有这些都无关紧要,例如:

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!

它会起作用,但要付出代价:每个new 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;他们并不是每次都创建一个新函数!现在,如果你有一个有十几个函数的类,你可以创建该类的一千个实例,而你在内存中仍然只有最初的十几个函数。效率高得多。

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

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

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