当前位置: 电脑软硬件应用网 > 设计学院 > 网络编程 > javascript > 正文 |
|
|||
javaScript面向对象定义类 | |||
2009-12-24 9:42:42 文/佚名 出处:网友博客 | |||
提起面向对象我们就能想到类,对象,封装,继承,多态,目前的javaScript资料中对这部分描述总是感觉不进人意,在《javaScript高级程序设计》(人民邮电出版社,曹力、张欣译。英文名字是:Professional JavaScript for Web Developers)这本书中描述的还算比较详细。我们看看JavaScript中定义类的各种方法。 javaScript中创建自己的类和对象,我们应该是必须掌握的,我们都知道javaScript中对象的属性可以在对象创建后动态定义,比如下面的代码: <SCRIPT LANGUAGE="JavaScript"> //定义 var oCar=new Object(); oCar.color="red"; oCar.doors=4; oCar.showColor=function() { alert(this.color); } //调用 oCar.showColor(); </SCRIPT> 我们很容易使用oCar对象,但是我们创就是想创建多个Car实例。我们可以使用一个函数来封装上面的代码来实现: <SCRIPT LANGUAGE="JavaScript"> //定义 function createCar() { var oCar=new Object(); oCar.color="red"; oCar.doors=4; oCar.showColor=function() { alert(this.color); } return oCar; } //调用 var ocar1=createCar(); var ocar2=createCar(); ocar1.color="black"; ocar1.showColor(); ocar2.showColor(); </SCRIPT> 顺便说一下,javaScript对象默认成员属性都是public 的。这种方式我们称为工厂方式,我们创造了能创建并返回特定类型的对象的工厂。 这样做有点意思了,但是在面向对象中我们经常使用创建对象的方法是: Car car=new Car(); 使用new 关键字已经深入人心,因此我们使用上面的方法去定义总感觉别扭,并且每次调用时都去创建新的属性以及函数,功能上也不实际。下来我们看看构造函数的形式定义类。 2.构造函数 这种方式看起来有点象工厂函数。具体表现如下: <SCRIPT LANGUAGE="JavaScript"> //定义 function Car(color,doors) { this.color=color; this.doors=doors; this.showColor=function() { alert(this.color); }; } //调用 var car1=new Car("red",4); var car2=new Car("blue",4); car1.showColor(); car2.showColor(); </SCRIPT> 看起来效果很明显,有差别了吧。感觉有点意思了。在构造函数内部创造对象使用this 关键字,使用new 运算符创建对象感觉非常亲切。但是也有点问题:每次new 对象时都会创建所有的属性,包括函数的创建,也就是说多个对象完全独立,我们定义类的目的就是为了共享方法以及数据,但是car1对象与car2对象都是各自独立的属性与函数,最起码我们应该共享方法。这就是原形方式的优势所在。 3.原型方式 利用对象的prototype属性,可把它看出创建新对象所依赖的原型。方法如下: <SCRIPT LANGUAGE="JavaScript"> //定义 function Car(){ }; Car.prototype.color="red"; Car.prototype.doors=4; Car.prototype.drivers=new Array("Tom","Jerry"); Car.prototype.showColor=function(){ alert(this.color); } //调用: var car1=new Car(); var car2=new Car(); car1.showColor(); car2.showColor(); alert(car1.drivers); car1.drivers.push("stephen"); alert(car1.drivers); //结果:Tom,Jerry,stephen alert(car2.drivers); //结果:Tom,Jerry,stephen </SCRIPT> 首先这段代码的构造函数,其中没有任何代码,接下来通过对象的prototype属性添加属性定义Car对象的属性。这种方法很好,但是问题是Car的对象指向的是Array指针,Car的两个对象都指向同一个Array数组,其中一个对象car1改变属性对象的引用(数组Array)时,另一个对象car2也同时改变,这是不允许的。 同时该问题也表现在原型不能带任何初始化参数,导致构造函数无法正常初始化。这需要另一种方式来解决:那就是混合的构造函数/原型模式。 4. 混合的构造函数/原型模式 联合使用构造函数和原型方式,定义类就非常方便。 <SCRIPT LANGUAGE="JavaScript"> //定义 function Car(color,doors) { this.color=color; this.doors=doors; this.drivers=new Array("Tom","Jerry"); } Car.prototype.showColor=function(){ alert(this.color); } //调用: var car1=new Car(“red”,4); var car2=new Car(“blue”,4); car1.showColor(); car2.showColor(); alert(car1.drivers); car1.drivers.push("stephen"); alert(car1.drivers); //结果:Tom,Jerry,stephen alert(car2.drivers); //结果:Tom,Jerry alert(car1 instanceof Car); </SCRIPT> 该方法是把属性放在内部定义,把方法放在外边利用prototype进行定义。解决了第三种方法的问题。 这种方法其实应该来说非常友好了,但是比起java的语法来,应该有一些不和谐,感觉比较凌乱,对C++来说,我们就没有那么麻烦的感觉了,可是开发C++的研发人员一般情况下很少涉及javaScript,而对J2EE的研发人员来说,这种方式总有一些别扭。总感觉不是友好的封装,其实只不过是视觉上封装效果不是很好而已,要想达到视觉封装效果而又能达到这种方法的效果的也可以以,个人认为其实比较麻烦。那就是动态原型法。 5.动态原型 这个方法需要检查对象定义的某一个动态属性如(_initialized)属性是否等于undefined,如果构造函数没有被调用则_initialized未定义,否则结束时定义为true即可,实现方法是: <SCRIPT LANGUAGE="JavaScript"> //定义 function Car() { this.color="red"; this.doors=4; this.drivers=new Array("Tom","Jerry"); if (typeof Car._initialized == "undefined") { Car.prototype.showColor=function() { alert(this.color); } //............ } //最后定义 Car._initialized=true; } </SCRIPT> 这种方法虽然在视觉上达到了封装,但是感觉总是别扭的,但是据说业界也很流行。我更喜欢看中第四种方法来定义类。 |
|||
关于45IT | About 45IT | 联系方式 | 版权声明 | 网站导航 | |
Copyright © 2003-2011 45IT. All Rights Reserved 浙ICP备09049068号 |