Javascript定义类的几种方式

我们可以认为,类,对象,封装,继承,多态性。在Javascript高级程序设计》(人民邮电出版社,Cao Li、张欣的翻译。英文名称:网站开发专业的Javascript)这本书比较详细的描述。我们在各种各样的Javascript中定义课方式看。

1。工厂模式

我们必须掌握Javascript中我们自己的类和对象的创建。我们都知道Javascript对象的属性可以在创建对象之后动态定义,例如,下面的代码:
复制代码代码如下所示:

定义
无功控=新的对象();
ocar.color =红色;
ocar.doors = 4;
ocar.showcolor =函数(){
警戒(这个颜色);
}
调用
OCar.showColor();


它很容易使用控对象,但我们创造了多车的情况下。我们可以用一个函数来封装上面的代码实现:
复制代码代码如下所示:

定义
功能createcar(){
无功控=新的对象();
ocar.color =红色;
ocar.doors = 4;
ocar.showcolor =函数(){
警戒(这个颜色);
}
返回控;
}
调用
无功ocar1 = createcar();
无功ocar2 = createcar();
ocar1.color =黑;
ocar1.showcolor();
ocar2.showcolor();


顺便说一下,Javascript对象的默认成员属性都是公共的,我们称之为工厂方式,我们创建了可以创建并返回特定类型对象的工厂。

这样做有点意思,但我们经常使用在面向对象中创建对象的方法:

汽车=新车();

新关键字的使用已经深入人心。因此,我们使用上述方法来定义笨拙的总感觉,并在每次调用时创建新的属性和函数,这在函数中也不实用。我们来看看构造函数的表单定义类。

2。构造函数

这种方式看起来有点像工厂的功能,具体表现如下:
复制代码代码如下所示:

定义
功能车(颜色,门){
this.color =颜色;
this.doors =门;
this.showcolor =函数(){
警戒(这个颜色);
};
}
调用
VaR CAR1 =新车(红
VaR的车=新车(蓝
car1.showcolor();
car2.showcolor();


它看起来是那么的明显,两者是有区别的。感觉有点有趣。创建在构造函数的对象使用此关键字,它是创造新的操作对象很友好,但也存在一些问题:新的对象每次将创建的所有属性,包括创造的功能,这是说有一个以上的对象是完全独立的,我们的目标是定义一个类是共享和数据,但是CAR1对象和车的对象是各自独立功能的财产,至少我们应该分享的方法。这是原始形式的优势。

三.原型模式

使用一个对象的原型属性,您可以看到它依赖于创建一个新对象的原型:
复制代码代码如下所示:

定义
函数汽车(){
};
car.prototype.color =红色;
car.prototype.doors = 4;
car.prototype.drivers =新的数组(汤姆
car.prototype.showcolor =函数(){
警戒(这个颜色);
}
调用:
VaR CAR1 =新车();
VaR的车=新车();
car1.showcolor();
car2.showcolor();
警报(CAR1。司机);
car1.drivers.push(史蒂芬);
警报(CAR1。司机); / /结果:汤姆,杰瑞,史蒂芬
警报(车。司机); / /结果:汤姆,杰瑞,史蒂芬



可以通过JSON原型模式简化定义:

= car.prototype
{
颜色:红色
门:4,
驱动程序:{汤姆
显示颜色对话框:函数(){
警戒(这个颜色);
}
}


首先,这个代码的构造函数,没有代码,然后定义汽车的性能对象添加属性到对象的原型。这个方法很好,但问题是,汽车指向数组的指针,两车点阵列相同的阵列之一CAR1改变对象引用对象的属性(阵列),另一个车的对象是在同一时间发生了变化,这是不允许的。

同时,该问题也表明原型不能提供任何初始化参数,导致构造函数不能正常初始化,需要另一种方法解决:即混合构造函数/原型模式。

4。混合构造函数/原型模式

使用构造函数和原型,定义类是非常方便的。
复制代码代码如下所示:

定义
功能车(颜色、门)
{
这个颜色=颜色;
门=门;
这个。驱动程序=新数组()
}

车。原型。调色精灵=函数(){
警戒(这个颜色);
}

调用:
VaR CAR1 =新车(',4);
VaR的车=新车(蓝色,4);

car1.showcolor();
car2.showcolor();

警报(CAR1。司机);
car1.drivers.push(史蒂芬);
警报(CAR1。司机); / /结果:汤姆,杰瑞,史蒂芬
警报(车。司机); / /结果:汤姆、杰瑞
Alert (Car1 instanceof Car);



这种方法是把属性放在内部定义中,并用外部的方法用原型来定义,解决了这第三种方法的问题。

这种方法其实应该是很友好的,但是相比于java语法,应该有一些不和谐,感觉比较乱,对于C++,我们就不会有这么多麻烦的感觉,但开发C++研发人员一般很少涉及Javascript和J2EE开发人员,总有这样一些尴尬。总的感觉是不友好的封装,但实际上它只是一个视觉封装效果。封装效果不是很好。如果我们想达到视觉封装的效果,我们也可以达到这种方法的效果,那就是动态原型。

5。动态原型

开发者使用其他语言,感觉不太和谐的使用一个混合的构造函数/原型。毕竟,大多数面向对象的语言有一个视觉封装在类定义的属性和方法,考虑下面的C #类:
复制代码代码如下所示:
类汽车
{
公共字符串颜色;
公共门= 4;
公共int = 23;

公共汽车(字符串颜色,整型门,int)
{
this.color =颜色;
this.doors =门;
this.mpg =英里;
}
公共无效显示颜色对话框() / /方法
{
console.writeline(的颜色);
}
}

C #善于包装的汽车类的所有属性和方法,所以看到这段代码知道它会实现,它定义了一个对象的信息。人批评混合构造函数/原型的方法,认为这是在构造函数中的记忆找到物业不合逻辑,和在构造函数中找到一个方法。因此,他们的设计是为了提供一个更加友好的编码风格的动态原型方法。

动态原型方法的基本思想是混合构造函数/原型的方式,那都是一样的,在构造函数的非功能属性的定义和功能属性是由原型属性定义的。唯一的区别就是给对象方法的位置。以下是重写的动态原型方法的汽车类:
复制代码代码如下所示:

定义
函数汽车(){
this.color =红色;
this.doors = 4;
this.drivers =新的数组(汤姆
如果(typeof的车。_initialized = = undefined){
car.prototype.showcolor =函数(){
警戒(这个颜色);
}
/ / ............
}
最后
_initialized =真车;
}


这个构造函数没有直到检查是否改变类型的车。_initialized等于未定义。这行代码是动态原型方法中最重要的部分。如果这个值不确定,构造函数将继续定义在一个原型对象的方法,然后设置车。_initialized真实。如果定义值(当它的值为true,typeof值是布尔值),然后该方法不再是创造。总之,该方法使用一个_initialized确定原型已经给出任何方法。这种方法是唯一的创造和分配一次请传统面向对象的开发人员,这看起来更像其他语言中的类定义。

6混合工厂模式

这通常是一种改变你不能应用以前方法的方式,其目的是创建一个错误的构造函数,只返回另一个对象的新实例。
复制代码代码如下所示:
函数汽车(){
无功otempcar =新的对象();
otempcar。颜色=红色;
otempcar门= 4;
otempcar MPG=23;
otempcar.showcolor =函数(){
警戒(这个颜色);
}
返回otempcar;
}

与经典方法不同,这种方法使用新操作符使其看起来像一个真正的构造函数:
无功控=新车();

因为新的运营商在车叫()构造函数,二新运营商(在构造函数)将被忽略。在构造函数创建对象传递回变变种,这种方法具有相同的问题作为对象方法的内部管理的经典方法,强烈建议:除非万不得已(请参阅第十五章),或避免使用这种方式。

概要:(以哪种方式)
使用最广泛的是混合构造函数/原型模式,此外,动态原型也很流行,它在功能上相当于一个构造函数/原型,可以使用这两种方法,但不要单独使用经典构造函数或原型,因为这将引入代码来解决问题。
复制代码代码如下所示:

静态类(1:函数)
该公司为新功能(VaR){
无功_carcollection =新的数组(); / /全球的私人
这个添加=功能(objcar){
警报('add);
}
这给=功能(CARiD){
警报(' ');
}
}

静态类(2:JSON)


var汽车{ { {
颜色:红',
门:4,
显示颜色对话框:函数(){ alert(这个颜色);}
}
Car.showColor();