已阅读5页,还剩7页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
5 自定义类和对象 5.1 工厂方法 在ECMAScript中创建工厂方法,返回一个特定类型的对象,以此实现代码的简洁适用。functioncreateFruit()vartempFruit=newObject;tempF=apple;tempFruit.number=5;tempFruit.showName=function()alert();returntempFruit;varFruit1=creatFruit();varFruit2=creatFruit(); 在createFruit()中可以加入形参来传入参数的值。随着ECMAScript不断被规范化,这种创建对象的方法已不再流行,一部分原因是语法上的,一部分原因是功能上的,如每个对象的实例都拥有属于自己的showName方法,给内存管理带来一定的开销。5.2 构造函数 选择一个类名,第一个字母大写,该类名即是构造函数的名称。创建一个构造函数和工厂方法比较类似,不同的是需要使用关键字new来创建对象的引用。使用构造函数的方式来创建对象和使用工厂方法有着相同的弊端。functionFruit(name,number)=name;this.number=number;this.showName=function()alert();varFruit1=newFruit(apple,5);varFruit2=newFruit(pear,3);5.3 使用 Prototype 使用prototype属性可以用来创建新的对象,首先需要一个空的构造函数建立类的名称,然后所有的属性和方法都直接分配到prototype属性中。functionFruit()F=apple;Ftotype.number=5;Ftotype.showName=function()alert();varfruit1=newFruit();varfruit2=newFruit(); 但是,这样同样存在一些缺点。首先,构造函数中没有参数,给初始化带来一些麻烦,其次,当一个属性指向的是一个对象而非方法时,该对象会被所有的实例所共享,任何一点改动都会影响到其他对象引用的使用。5.4 混合使用工厂方法和Prototype这个概念很简单:使用构造函数定义所有除方法外的属性,使用 prototype 定义对象的方法。这样每个方法只会被创建一次,每个对象都能拥有自己对象实例的属性。functionFruit(name,number)=name;this.number=number;this.owner=newArray(Jerry,Terry);Ftotype.showName=function()alert();varFruit1=newFruit(apple,5);varFruit2=newFruit(pear,3);5.5 动态 prototype 简单来说,这种方法就是使用了一个标识符来判断 prototype 是否已经被指向某个方法,从而保证这些方法只会被创建并指向一次。5.6 混合工厂方法 这种方法和经典的工厂方法及构造函数方法在对象方法内存管理上存在同样的问题,一般不建议使用该方法,除了某些特殊情况(XML in JavaScript中有这样的例子)。6 修改对象 使用prototype对象可以对对象进行修改。除了用户自定义的对象外,ECMAScript原始对象也有prototype属性。直接使用 prototype可以给对象创建新的方法。Ntotype.toHexString=function()returnthis.toString(16);variNum=10;alert(iNum.toHexString();/输出A 另外,使用prototype可以轻松修改已有的方法,让方法名指向新的方法。需要注意的是,指向新的方法后,原有的方法不再被任何对象使用,将会被垃圾回收器销毁,使得原有方法不再存在。比较安全的解决办法是,建立一个新的引用来保存原有的方法,然后再将原方法覆盖。 比较特殊的是,ECMAScript中创建对象,在对象引用被创建后,可以给对象加入新的方法,并且可以立即在对象的引用中使用。这是ECMAScript的一个特性,但不推荐这样使用,以免带来不必要的麻烦,例如阅读理解、文档资料等。第一种方式: 工厂方法 能创建并返回特定类型的对象的工厂函数(factory function)。 Javascript代码 1. functioncreateCar(sColor) 2. varoTempCar=newObject; 3. oTempCar.color=sColor; 4. oTempCar.showColor=function() 5. alert(this.color); 6. ; 7. returnoTempCar; 8. 9. varoCar1=createCar(); 10. varoCar2=createCar();function createCar(sColor) var oTempCar = new Object; oTempCar.color = sColor; oTempCar.showColor = function () alert(this.color); ; return oTempCar;var oCar1 = createCar();var oCar2 = createCar();调用此函数时,将创建新对象,并赋予它所有必要的属性。使用此方法将创建car对象的两个版本(oCar1和oCar2),他们的属性完全一样。 使用此方法存在的问题: 1语义上看起来不像使用带有构造函数的new运算符那么正规。 2使用这种方式必须创建对象的方法。每次调用createCar(),都要创建showColor(),意味着每个对象都有自己的showColor()版本,事实上,每个对象都共享了同一个函数。 有些开发者在工厂函数外定义对象的方法,然后通过属性指向该方法。从而避免这个问题: Js代码 1. functioncreateCar(sColor) 2. varoTempCar=newObject; 3. oTempCar.color=sColor; 4. oTempCar.showColor=showColor; 5. returnoTempCar; 6. 7. functionshowColor() 8. alert(this.color); 9. function createCar(sColor) var oTempCar = new Object; oTempCar.color = sColor; oTempCar.showColor = showColor; return oTempCar;function showColor() alert(this.color);在这段重写的代码中,在函数createCar()前定义了函数showColor().在createCar()内部,赋予对象一个已经指向已经存在的showColor()函数的指针。从功能上来讲,这样解决了重复创建对象的问题,但该函数看起来不像对象的方法。 所有这些问题引发了开发者定义的构造函数的出现。 第二种方式:构造函数方式 Js代码 1. functionCar(sColor) 2. this.color=sColor; 3. this.showColor=function() 4. alert(this.color); 5. ; 6. 7. varoCar1=newCar(red); 8. varoCar2=newCar(blue);function Car(sColor) this.color = sColor; this.showColor = function () alert(this.color); ;var oCar1 = new Car(red);var oCar2 = new Car(blue);你可能已经注意到第一个差别了,在构造函数内部无创建对象,而是使用this关键字。使用new运算符调用构造函数时,在执行第一行代码前先创建一个对象,只有用this才能访问该对象。然后可以直接赋予this属性,默认情况下是构造函数的返回值(不必明确使用return运算符)。 这种方式在管理函数方面与工厂方法一样都存在相同的问题。 第三种方式:原型方式 Js代码 1. functionCar() 2. 3. 4. Ctotype.color=blue; 5. varoCar1=newCar(); 6. varoCar2=newCar();function Car() Ctotype.color = blue;var oCar1 = new Car();var oCar2 = new Car();调用new Car()时,原型的所有属性都被立即赋予要创建的对象,意味着所有的Car实例存放的都是指向showColor()函数的指针。从语义上看起来都属于一个对象,因此解决了前面两种方式存在的两个问题。此外使用该方法,还能用instanceof运算符检查给定变量指向的对象类型。因此,下面的代码将输出true: alert(oCar instanceof Car); /outputs true 这个方式看起来很不错,遗憾的是,它并不尽如人意。 1首先这个构造函数没有参数。使用原型方式时,不能给构造函数传递参数初始化属性的值,因为car1和car2的属性都等于“red”。 2真正的问题出现在属性指向的是对象,而不是函数时。函数共享不会造成任何问题,但是对象却很少被多个实例共享的。 第四种方式:混合的构造函数/原型方式(推荐) 联合使用构造函数和原型方式,就可像用其他程序设计语言一样创建对象。这种概念非常简单,即用构造函数定义对象的所有非函数属性,用原型方式定义对象的函数属性(方法)。 Js代码 1. functionCar(sColor) 2. this.color=sColor; 3. this.drivers=newArray(Mike,Sue); 4. 5. Ctotype.showColor=function() 6. alert(this.color); 7. 8. varoCar1=newCar(red); 9. varoCar2=newCar(blue); 10. 11. oCar1.drivers.push(Matt); 12. 13. alert(oCar1.drivers);/outputsMike,Sue,Matt 14. alert(oCar1.drivers);/outputsMike,Suefunction Car(sColor) this.color =sColor; this.drivers =new Array(Mike,Sue);Ctotype.showColor = function() alert(this.color);var oCar1 =new Car(red);var oCar2 =new Car(blue);oCar1.drivers.push(Matt);alert(oCar1.drivers); /outputs Mike,Sue,Mattalert(oCar1.drivers); /outputs Mike,Sue第五种方式:动态原型方式(推荐) 对于习惯使用其他语言的开发者来说,使用混合的构造函数/原型方式感觉不那么和谐。批评混合的构造函数/原型方式的人认为,在构造函数内找属性,在外部找方法的做法很不合理。所以他们设计了动态原型方式,以提供更友好的编码风格。 动态原型方法的基本想法与混合的构造函数/原型方式相同,即在构造函数内定义非函数属性,而函数属性则利用原型属性定义。唯一的区别是赋予对象方法的位置。下面是使用动态原型方法重写的Car类: Js代码 1. functionCar(sColor) 2. this.color=sColor; 3. this.drivers=newArray(Mike,Sue); 4. 5. if(typeofCar._initialized=undefined) 6. Ctotype.showColor=function() 7. alert(this.color); 8. 9. 10. Car._initialized=true; 11. =function Car(sColor) this.color =sColor; this.drivers =new Array(Mike,Sue); if(typeof Car._initialized = undefined) Ctotype.showColor = function() alert(this.color); Car._initialized = true;Javascript本身并不支持面向对象,它没有访问控制符,它没有定义类的关键字class,它没有支持继承的extend或冒号,它也没有用来支持虚函数的virtual,不过,Javascript是一门灵活的语言,下面我们就看看没有关键字class的Javascript如何实现类定义,并创建对象。一:定义类并创建类的实例对象在Javascript中,我们用function来定义类,如下:function Shape() var x=1; var y=2;你或许会说,疑?这个不是定义函数吗?没错,这个是定义函数,我们定义了一个Shape函数,并对x和y进行了初始化。不过,如果你换个角度来看,这个就是定义一个Shape类,里面有两个属性x和y,初始值分别是1和2,只不过,我们定义类的关键字是function而不是class。然后,我们可以创建Shape类的对象aShape,如下:var aShape = new Shape();二:定义公有属性和私有属性我们已经创建了aShape对象,但是,当我们试着访问它的属性时,会出错,如下:aShape.x=1;这说明,用var定义的属性是私有的。我们需要使用this关键字来定义公有的属性function Shape() this.x=1; this.y=2;这样,我们就可以访问Shape的属性了,如。aShape.x=2;好,我们可以根据上面的代码总结得到:用var可以定义类的private属性,而用this能定义类的public属性。三:定义公有方法和私有方法在 Javascript中,函数是Function类的实例,Function间接继承自Object,所以,函数也是一个对象,因此,我们可以用赋值的方法创建函数,当然,我们也可以将一个函数赋给类的一个属性变量,那么,这个属性变量就可以称为方法,因为它是一个可以执行的函数。代码如下:function Shape() var x=0; var y=1; this.draw=function() /print; ;我们在上面的代码中定义了一个draw,并把一个function赋给它,下面,我们就可以通过aShape调用这个函数,OOP中称为公有方法,如:aShape.draw();如果用var定义,那么这个draw就变成私有的了,OOP中称为私有方法,如function Shape() var x=0; var y=1; var draw=function() /print; ;这样就不能使用aShape.draw调用这个函数了。三:构造函数Javascript并不支持OOP,当然也就没有构造函数了,不过,我们可以自己模拟一个构造函数,让对象被创建时自动调用,代码如下:function Shape() var init = function() /构造函数代码 ; init();在Shape的最后,我们人为的调用了init函数,那么,在创建了一个Shape对象是,init总会被自动调用,可以模拟我们的构造函数了。四:带参数的构造函数如何让构造函数带参数呢?其实很简单,将要传入的参数写入函数的参数列表中即可,如function Shape(ax,ay) var x=0; var y=0; var init = function() /构造函数 x=ax; y=ay; ; init();这样,我们就可以这样创建对象:var aShape = new Shape(0,1);五:静态属性和静态方法在Javascript中如何定义静态的属性和方法呢?如下所示function Shape(ax,ay) var x=0; var y=0; var init = function() /构造函数 x=ax; y=ay; ; init();Shape.count=0;/定义一个静态属性count,这个属性是属于类的,不是属于对象的。Shape.staticMethod=function();/定义一个静态的方法有了静态属性和方法,我们就可以用类名来访问它了,如下alert ( aShape.count );aShape.staticMethod();注意:静态属性和方法都是公有的,目前为止,我不知道如何让静态属性和方法变成私有的六:在方法中访问本类的公有属性和私有属性在类的方法中访问自己的属性,Javascript对于公有属性和私有属性的访问方法有所不同,请大家看下面的代码function Shape(ax,ay) var x=0; var y=0; this.gx=0; this.gy=0; var init = function() x=ax;/访问私有属性,直接写变量名即可 y=ay; this.gx=ax;/访问公有属性,需要在变量名前加上this. this.gy=ay; ; init();七:this的注意事项根据笔者的经验,类中的this并不是一直指向我们的这个对象本身的,主要原因还是因为Javascript并不是OOP语言,而且,函数和类均用function定义,当然会引起一些小问题。this指针指错的场合一般在事件处理上面,我们想让某个对象的成员函数来响应某个事件,当事件被触发以后,系统会调用我们这个成员函数,但是,传入的this指针已经不是我们本身的对象了,当然,这时再在成员函数中调用this当然会出错了。解决方法是我们在定义类的一开始就将this保存到一个私有的属性中,以后,我们可以用这个属性代替this。我用这个方法使用this指针相当安全,而且很是省心我们修改一下代码,解决this问题。对照第六部分的代码看,你一定就明白了function Shape(ax,ay) var _this=this; /把this保存下来,以后
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2025年企业合规师考试及答案
- 2025至2030中国复合砌块行业调研及市场前景预测评估报告
- 2025-2030中国液体化学品物流产业链价值评估与商业机遇研究报告
- 2025-2030中国切菜机行业人工成本上涨关联性报告
- 高效能灌装生产线行业2026年产业发展现状及未来发展趋势分析研究
- 2025液晶显示面板制造工艺良率提升与产业链上下游协同研究
- 2025液晶显示屏技术研发市场竞争格局市场需求市场发展分析报告
- 2025液压系统代理行业市场深度剖析及变革趋势与商业价值分析报告
- 2025液体饮料包装材料与高新技术塑料行业市场进入壁垒分析竞争格局调整规划报告
- 2025消费级3D打印材料创新与个性化定制商业模式探索报告
- 2025年医学高数期末考试题及答案
- 中药药食同源开发项目分析方案
- 2025版更年期综合征症状讲解及护理要点
- 水库物业化管理项目管理组织架构及人员配备
- 企业统计知识培训会课件
- 回收废钢知识培训内容课件
- 小学教师外出学习汇报材料
- 复合材料模具性能测试规定
- 2025公寓保洁服务承包合同
- 乡村振兴视角下环江县农村公共文化服务的政府供给优化研究
- GB/T 46229-2025喷砂用橡胶软管
评论
0/150
提交评论