是的,我真的不明白你为什么要避开构造函数方法,或者当构造函数本身是优雅、灵活、以及完全合理的面向对象编程方法,无论像 Crockford 这样的人给出了多少不喜欢它们的蹩脚理由(因为人们忘记使用新关键字 - 认真吗?)。JS 是高度功能驱动的,它的 OOP 机制也不例外。接受这一点比躲避它更好,IMO。
首先,您的积分列在“显然”下
在 JavaScript 中几乎不值得一提。高度可变性是设计使然。我们不怕我们自己或其他 JavaScript 开发人员。私有与公共范式没有用,因为它可以保护我们免于愚蠢,而是因为它可以更容易地理解其他开发人员代码背后的意图。
调用的努力不是问题。当你不清楚你为什么做了你在那里做过的事情时,麻烦就来了。我真的看不出你想要实现的核心语言方法对你没有更好的效果。
这是 JavaScript。多年来,除了 JS 开发人员之外,所有人都觉得很奇怪。如果您找到一种更好的方法来解决给定领域中的问题,而不是更典型的解决方案,请不要担心。在尝试替换它之前,请确保您了解更典型方法的要点,就像许多人从其他语言范式转向 JS 时所做的那样。用 JS 做一些琐碎的事情很容易,但是一旦你到了想要获得更多 OOP 驱动的地步,尽你所能了解核心语言的工作原理,这样你就可以对流行的观点提出更多的怀疑。那些以副业为生的人让 JavaScript 变得比实际情况更可怕,更充满致命的诱杀陷阱。
现在你在“积极的一面”下的观点
首先,重复的函数定义实际上只是在繁重的循环场景中需要担心的事情。如果您定期以足够快的速度生成足够多的对象,以使非原型公共方法定义成为性能问题,那么无论如何,您可能会在短时间内遇到非平凡对象的内存使用问题。然而,我用过去时说,因为无论哪种方式,它都不再是一个真正相关的问题。在现代浏览器中,由于现代 JIT 编译器的工作方式,在其他函数中定义的函数实际上通常会提高性能。无论您支持什么浏览器,每个对象定义的几个函数都不是问题,除非您期望有数万个对象。
关于简单易懂的问题,这不是我的问题,因为我看不出你在这里获得了什么胜利。现在,我不必使用一个对象,而是必须同时使用该对象和它的伪构造函数. 如果我是您的代码库的新手,我会浪费大量时间试图弄清楚您为什么这样做以避免破坏我不理解的其他一些问题。
我的问题是:
为什么不首先在构造函数中添加对象字面量中的所有方法呢?那里没有性能问题,而且从来没有真正存在过,所以唯一可能的胜利是您希望能够在使用它创建新对象后向人员添加新方法,但这就是我们在适当的构造函数上使用原型的原因(顺便说一句,原型方法非常适合旧浏览器中的内存,因为它们只定义一次)。
而且,如果您必须不断传递对象以使方法知道属性是什么,那您为什么还要对象呢?为什么不只是期望具有某些属性的简单数据结构类型对象的函数呢?它不再是真正的 OOP。
但我的主要批评点
您错过了 OOP 的要点,这是 JavaScript 在不向人们隐藏方面比大多数语言做得更好。考虑以下:
function Person(name){
//var name = name; //<--this might be more clear but it would be redundant
this.identifySelf = function(){ alert(name); }
}
var bob = new Person();
bob.identifySelf();
现在,在不覆盖对象或方法的情况下更改 bob 标识的名称,这两种操作只有在您明确不想使用最初设计和构造的对象时才要做。你当然不能。这让任何看到这个定义的人都清楚地知道,在这种情况下,名称实际上是一个常数。在更复杂的构造函数中,它将确定唯一允许更改或修改名称的是实例本身,除非用户添加了一个非验证的 setter 方法,这将是愚蠢的,因为这基本上会(看着你的 Java Enterprise Beans)谋杀OOP 的主要目的。
分工明确是关键
暂时忘掉他们在每本书中的关键词,想想重点是什么。在 OOP 之前,一切都只是一堆函数和所有这些函数所作用的数据结构。使用 OOP,您通常拥有一组与一组数据捆绑在一起的方法,而这些数据实际上只有对象本身会发生变化。
所以让我们说输出出了点问题:
大多数时候暴露所有数据的对象实际上只比旧的程序方法稍微好一点。真正做的只是给你一个名字来分类松散相关的方法。
很多关于“这个”的事
我从来没有理解分配给“this”关键字的过度关注是混乱和混乱的。这真的没什么大不了的。'this' 标识您正在使用的实例。就是这样。如果该方法不作为属性调用,则它不会知道要查找的实例,因此它默认为全局对象。那是愚蠢的(未定义会更好),但是在这种情况下它不能正常工作应该在一种语言中预期,其中函数也像数据一样可移植并且可以很容易地附加到其他对象。在以下情况下在函数中使用“this”:
但请记住,真正重要的是召唤。将公共方法分配给某个 var 并从该 var 调用将执行全局操作或在严格模式下引发错误。在没有被引用为对象属性的情况下,函数只真正关心它们定义的范围(它们的闭包)以及您传递给它们的参数。