很长一段时间我一直在做JavaScript类做以下
function MyClass(){
this.v1;
this.foo = function(){
return true;
}
};
然后我找到TypeScript,看起来它把它的类编译成
var MyClass = (function () {
function MyClass(message) {
this.v1 = message;
}
MyClass.prototype.foo = function () {
return "Hello, " + this.v1;
};
return MyClass;
})();
我在网上发现的另一个方法是
var MyClass = {
v1:1,
foo: function(){
return true;
}
};
这对我来说看起来很丑,但也许我错过了这个方法的一些有益的东西,因为它看起来是大多数人在javaScript中做对象的方式。
我能够从我创建的函数继承的第一个方法。
Function.prototype.extends = function(parent){
this.prototype = new parent();
this.prototype.constructor = this;
};
我也见过很多在JavaScript中创建类的方法。我想知道如果我的方法是错误的,或者如果有做面向对象的最佳实践方法。我所做的所有项目都使用第一个例子。你可以在https://github.com/Patrick-W-McMahon上看到,现在我看到JavaScript编译器在做什么,我开始质疑我的方法。我想知道其他JavaScript程序员建议什么是最好的方法,如果有方法之间的差异。我有c++/Java背景,因此我编写的JavaScript与我的背景相匹配。
你在这里读到的被称为power构造函数,更多信息在这里:
Douglas Crockford谈遗产
作为一种多范式语言,JavaScript非常适合这些不同的考虑。事实是,它以你所能想象的方式塑造了你的大脑。
换句话说,如果你能用一种方式来推断你的结构,那就用这种方式。
另一方面,如果您希望完全"自由"于您自己的约束,那么您应该完全放弃类中的推理,并接受原型继承,而不需要任何类似于类的东西。鸭子类型是一个自然的结果,在极端情况下,你会到处使用闭包。我经常这样做:
function myItemBuilder(p1)
{
var s0, p0 = 0;
// s0 is a shared private property (much like static in classes)
// p0 is a shared private property but will be factorized (rendered non-shared)
// p1 is a private instance property
return (function (p0) { // factorize p0 if necessary
return {
publicProperty : 3,
method1 : function (arg1) {
// code here (may use publicProperty, arg1, s0, p0 (factorized) and p1)
},
method2 : function (arg2) {
// code here (may use publicProperty, arg2, s0, p0 (factorized) and p1)
}
};
}(p0++)); // on each invocation p0 will be different and method1/method2 will not interfere across invocations (while s0 is shared across invocations)
}
EDIT:内部闭包仅在需要分解p0时才需要(即在每次调用时为p0设置单独的独立值)。当然,如果不需要分解p0,可以省略内部闭包。
上面的例子故意比需要的更复杂,以说明各种有趣的情况。
像myItemBuilder("hello")
那样调用这个方法构建了一个具有这些特定功能的新项目,但实际上没有class
构造本身。
当你想放弃经典继承时,这是获取实例的一种特别强大的方式。例如,在c++中,您可以从多个类继承,这称为mix-in。在Java和c#中,你只有单继承,但是接口可以帮助你。
在这里,我上面展示的是装配线隐喻,它可以将组件组装到一个实例中,结果是在类、接口和混合之间没有具体的(1)区别。它们都只是具有特性的实例,可以通过元编程(duck typing,反射/检查)进行反映。逻辑(2)区别在于:(1)具体实例的行为与它们产生的方式无关,但(2)逻辑上接口是契约,而实例是实现。如果你真正理解SOLID和装配线比喻,所有这些都是有意义的。否则,请原谅我这么长时间的回答:)
补充道:
使用这种方法,您不能检查类型,但您不需要检查类型,因为duck类型允许您找到所需的方法,而无需查看类或接口契约。这类似于将每个方法放在单独的单方法接口中。
此处说明
http://www.2ality.com/2011/06/coffeescript-classes.html一个普通的JavaScript类定义,封装在IIFE[3]中。在这里使用IIFE没有任何好处,除了有一个单一的赋值(这在对象字面量中很重要,但在这里没有)。
这是个人喜好的问题。使用这个方法
var MyClass = {
v1:1,
foo: function(){
return true;
}
};
导致更少的字符,因此更小的JS文件,所以这是我通常使用的方法,但没有错误或正确的方式。顺便说一句。既然您评论过这种类型的对象构造是丑陋的,那么您可能想要坚持使用您所习惯的。然而,如果你觉得冒险,看看这个项目。
它使javascript中的oop快速,无痛且不难看。此外,它还正确支持多重继承。