已阅读5页,还剩16页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
Javascript中的类实现Javascript本身并不支持面向对象,它没有访问控制符,它没有定义类的关键字class,它没有支持继承的extend或冒号,它也没有用来支持虚函数的virtual,不过,Javascript是一门灵活的语言,下面我们就看看没有关键字class的Javascript如何实现类定义,并创建对象。一:定义类并创建类的实例对象在Javascript中,我们用function来定义类,如下:functionShape()varx=1;vary=2;你或许会说,疑?这个不是定义函数吗?没错,这个是定义函数,我们定义了一个Shape函数,并对x和y进行了初始化。不过,如果你换个角度来看,这个就是定义一个Shape类,里面有两个属性x和y,初始值分别是1和2,只不过,我们定义类的关键字是function而不是class。然后,我们可以创建Shape类的对象aShape,如下:varaShape=newShape();二:定义公有属性和私有属性我们已经创建了aShape对象,但是,当我们试着访问它的属性时,会出错,如下:aShape.x=1;这说明,用var定义的属性是私有的。我们需要使用this关键字来定义公有的属性functionShape()this.x=1;this.y=2;这样,我们就可以访问Shape的属性了,如。aShape.x=2;好,我们可以根据上面的代码总结得到:用var可以定义类的private属性,而用this能定义类的public属性。三:定义公有方法和私有方法在Javascript中,函数是Function类的实例,Function间接继承自Object,所以,函数也是一个对象,因此,我们可以用赋值的方法创建函数,当然,我们也可以将一个函数赋给类的一个属性变量,那么,这个属性变量就可以称为方法,因为它是一个可以执行的函数。代码如下:functionShape()varx=0;vary=1;this.draw=function()/print;我们在上面的代码中定义了一个draw,并把一个function赋给它,下面,我们就可以通过aShape调用这个函数,OOP中称为公有方法,如:aShape.draw();如果用var定义,那么这个draw就变成私有的了,OOP中称为私有方法,如functionShape()varx=0;vary=1;vardraw=function()/print;这样就不能使用aShape.draw调用这个函数了。三:构造函数Javascript并不支持OOP,当然也就没有构造函数了,不过,我们可以自己模拟一个构造函数,让对象被创建时自动调用,代码如下:functionShape()varinit=function()/构造函数代码;init();在Shape的最后,我们人为的调用了init函数,那么,在创建了一个Shape对象是,init总会被自动调用,可以模拟我们的构造函数了。四:带参数的构造函数如何让构造函数带参数呢?其实很简单,将要传入的参数写入函数的参数列表中即可,如functionShape(ax,ay)varx=0;vary=0;varinit=function()/构造函数x=ax;y=ay;init();这样,我们就可以这样创建对象:varaShape=newShape(0,1);五:静态属性和静态方法在Javascript中如何定义静态的属性和方法呢?如下所示functionShape(ax,ay)varx=0;vary=0;varinit=function()/构造函数x=ax;y=ay;init();Shape.count=0;/定义一个静态属性count,这个属性是属于类的,不是属于对象的。Shape.staticMethod=function();/定义一个静态的方法有了静态属性和方法,我们就可以用类名来访问它了,如下alert( Shape.count);Shape.staticMethod();注意:静态属性和方法都是公有的,目前为止,我不知道如何让静态属性和方法变成私有的六:在方法中访问本类的公有属性和私有属性在类的方法中访问自己的属性,Javascript对于公有属性和私有属性的访问方法有所不同,请大家看下面的代码functionShape(ax,ay)varx=0;vary=0;this.gx=0;this.gy=0;varinit=function()x=ax;/访问私有属性,直接写变量名即可y=ay;this.gx=ax;/访问公有属性,需要在变量名前加上this.this.gy=ay;init();七:this的注意事项根据笔者的经验,类中的this并不是一直指向我们的这个对象本身的,主要原因还是因为Javascript并不是OOP语言,而且,函数和类均用function定义,当然会引起一些小问题。this指针指错的场合一般在事件处理上面,我们想让某个对象的成员函数来响应某个事件,当事件被触发以后,系统会调用我们这个成员函数,但是,传入的this指针已经不是我们本身的对象了,当然,这时再在成员函数中调用this当然会出错了。应网友moon的建议,加上this指错的例子functionShape()varx=123;varinit=function()alert(this.x);/此处会输出undefined,而不是123,原因:此处的this属于init这个function内部,而init这个function中并没有定义x这个变量;init();varshape=newShape();解决方法是我们在定义类的一开始就将this保存到一个私有的属性中,以后,我们可以用这个属性代替this。我用这个方法使用this指针相当安全,而且很是省心我们修改一下代码,解决this问题。对照第六部分的代码看,你一定就明白了functionShape(ax,ay)var_this=this;/把this保存下来,以后用_this代替this,这样就不会被this弄晕了varx=0;vary=0;_this.gx=0;_this.gy=0;varinit=function()x=ax;/访问私有属性,直接写变量名即可y=ay;_this.gx=ax;/访问公有属性,需要在变量名前加上this._this.gy=ay;init();以上我们聊了如何在Javascript中定义类,创建类的对象,创建公有和私有的属性和方法,创建静态属性和方法,模拟构造函数,并且讨论了容易出错的this。关于Javascript中的OOP实现就聊到这里,以上是最实用的内容,一般用Javascript定义类,创建对象用以上的代码已经足够了。当然,你还可以用mootools或prototype来定义类,创建对象。我用过mootools框架,感觉很不错,它对Javascript的类模拟就更完善了,还支持类的继承,有兴趣的读者可以去尝试一下。当然,如果使用了框架,那么在你的网页中就需要包含相关的js头文件,因此我还是希望读者能够在没有框架的情况下创建类,这样,代码效率较高,而且你也可以看到,要创建一个简单的类并不麻烦在下一个版本的Javascript中,将会加入对OOP的支持,届时,我们将看到class关键字,public、private访问控制符extend继承。如果大家对下一代Javascript感兴趣,不妨可以先接触一下ActionScript3.0,这是一门相当先进的脚本语言,是Adobe收购Macromedia后的一个力作,它和Javascript一样,都属于ECMAScript,只不过AS3.0是ECMAScript的第4版的实现。要学习ActionScript3.0,我重点推荐孙颖老师的ActionScript3殿堂之路,这本书写的绝对好,特别是面向对象这部分,写的特别通俗易懂,例子生动,读完以后感觉很有收获,在赞叹新版的ECMAScript的同时,也给了我极大的动力继续深入学习OOP编程思想,有兴趣的读者不妨去品读一下Javascript定义类(class)的三种方法作者:阮一峰日期:2012年7月 9日将近20年前,Javascript诞生的时候,只是一种简单的网页脚本语言。如果你忘了填写用户名,它就跳出一个警告。如今,它变得几乎无所不能,从前端到后端,有着各种匪夷所思的用途。程序员用它完成越来越庞大的项目。Javascript代码的复杂度也直线上升。单个网页包含10000行Javascript代码,早就司空见惯。2010年,一个工程师透露,Gmail的代码长度是443000行!编写和维护如此复杂的代码,必须使用模块化策略。目前,业界的主流做法是采用面向对象编程。因此,Javascript如何实现面向对象编程,就成了一个热门课题。麻烦的是,Javascipt语法不支持类(class),导致传统的面向对象编程方法无法直接使用。程序员们做了很多探索,研究如何用Javascript模拟类。本文总结了Javascript定义类的三种方法,讨论了每种方法的特点,着重介绍了我眼中的最佳方法。=Javascript定义类(class)的三种方法作者:阮一峰在面向对象编程中,类(class)是对象(object)的模板,定义了同一组对象(又称实例)共有的属性和方法。Javascript语言不支持类,但是可以用一些变通的方法,模拟出类。一、构造函数法这是经典方法,也是教科书必教的方法。它用构造函数模拟类,在其内部用this关键字指代实例对象。function Cat() = 大毛;生成实例的时候,使用new关键字。var cat1 = new Cat();alert(); / 大毛类的属性和方法,还可以定义在构造函数的prototype对象之上。Ctotype.makeSound = function()alert(喵喵喵);关于这种方法的详细介绍,请看我写的系列文章Javascript 面向对象编程,这里就不多说了。它的主要缺点是,比较复杂,用到了this和prototype,编写和阅读都很费力。二、Object.create()法为了解决构造函数法的缺点,更方便地生成对象,Javascript的国际标准ECMAScript第五版(目前通行的是第三版),提出了一个新的方法Object.create()。用这个方法,类就是一个对象,不是函数。var Cat = name: 大毛,makeSound: function() alert(喵喵喵); ;然后,直接用Object.create()生成实例,不需要用到new。var cat1 = Object.create(Cat);alert(); / 大毛cat1.makeSound(); / 喵喵喵目前,各大浏览器的最新版本(包括IE9)都部署了这个方法。如果遇到老式浏览器,可以用下面的代码自行部署。if (!Object.create) Object.create = function (o) function F() F.prototype = o;return new F();这种方法比构造函数法简单,但是不能实现私有属性和私有方法,实例对象之间也不能共享数据,对类的模拟不够全面。三、极简主义法荷兰程序员Gabor de Mooij提出了一种比Object.create()更好的新方法,他称这种方法为极简主义法(minimalist approach)。这也是我推荐的方法。3.1 封装这种方法不使用this和prototype,代码部署起来非常简单,这大概也是它被叫做极简主义法的原因。首先,它也是用一个对象模拟类。在这个类里面,定义一个构造函数createNew(),用来生成实例。var Cat = createNew: function()/ some code here;然后,在createNew()里面,定义一个实例对象,把这个实例对象作为返回值。var Cat = createNew: function()var cat = ; = 大毛;cat.makeSound = function() alert(喵喵喵); ;return cat;使用的时候,调用createNew()方法,就可以得到实例对象。var cat1 = Cat.createNew();cat1.makeSound(); / 喵喵喵这种方法的好处是,容易理解,结构清晰优雅,符合传统的面向对象编程的构造,因此可以方便地部署下面的特性。3.2 继承让一个类继承另一个类,实现起来很方便。只要在前者的createNew()方法中,调用后者的createNew()方法即可。先定义一个Animal类。var Animal = createNew: function()var animal = ;animal.sleep = function() alert(睡懒觉); ;return animal;然后,在Cat的createNew()方法中,调用Animal的createNew()方法。var Cat = createNew: function()var cat = Animal.createNew(); = 大毛;cat.makeSound = function() alert(喵喵喵); ;return cat;这样得到的Cat实例,就会同时继承Cat类和Animal类。var cat1 = Cat.createNew();cat1.sleep(); / 睡懒觉3.3 私有属性和私有方法在createNew()方法中,只要不是定义在cat对象上的方法和属性,都是私有的。var Cat = createNew: function()var cat = ;var sound = 喵喵喵;cat.makeSound = function() alert(sound); ;return cat;上例的内部变量sound,外部无法读取,只有通过cat的公有方法makeSound()来读取。var cat1 = Cat.createNew();alert(cat1.sound);/ undefined3.4 数据共享有时候,我们需要所有实例对象,能够读写同一项内部数据。这个时候,只要把这个内部数据,封装在类对象的里面、createNew()方法的外面即可。var Cat = sound : 喵喵喵,createNew: function()var cat = ;cat.makeSound = function() alert(Cat.sound); ;cat.changeSound = function(x) Cat.sound = x; ;return cat;然后,生成两个实例对象:var cat1 = Cat.createNew();var cat2 = Cat.createNew();cat1.makeSound(); / 喵喵喵这时,如果有一个实例对象,修改了共享的数据,另一个实例对象也会受到影响。cat2.changeSound(啦啦啦);cat1.makeSound(); / 啦啦啦用JavaScript模拟经典类大家熟知JavaScript是基于原型的编程语言,并没有包含内部类的实现。但是通过JavaScript可以轻易地模拟出经典的类。今天这篇分享,就向大家介绍一种用JavaScript模拟经典类的方法。方法有很多种,这只是笔者所知道的一种,其他别的方式大家也可以提出来,相互参考学习。当然,文中难免会有一些错误之处,望大家瞪大了眼睛,细心发现,狠狠拍砖。闲话就不多扯了,现在开始我们的正题=用用JavaScript模拟经典类。第一步:创建自己的“类模拟库”。var Class=function(parent)var klass=function()this.init.apply(this,arguments);totype.init=function();return klass;这样我们就创建了一个类模拟库,下面我们可以用这个“类模拟库”来创建我们的类。/创建一个Person类var Person=new Class;Ptotype.init=function()/基于Person的实例做初始化/创建person实例var person=new Person;第一步完成了,是不是感觉很没劲,觉得这样做没什么不同,这个类库似乎显得有些多余。不急,我们慢慢向下看。第二步:给类库添加方法。var Class=function(parent)var klass=function()this.init.apply(this,arguments);/改变klass的原型if(parent)var subclass=function();totype=totype;totype=new subclass;totype.init=function();/定义prototype的别名klass.fn=totype;/定义类的别名klass.fn.parent=klass;/给类添加属性的方法extend()klass.extend=function(obj)for(var i in obj)klassi=obji;/给实例添加属性的方法include()klass.include=function(obj)for (var i in obj) klass.fni=obji;return klass;给我们的类库添加了两个函数(用红色注释标出),这样我们的类库就变得强大了。强大在哪里呢?就强大在这两个添加的函数上面,现在来解释一下这两个函数的作用:extend()函数:参数是一个对象,现在可以用其来生成一个类,通过迭代对象的属性直接复制到类上。var Person=new Class;Person.extend(find: function()/*.*/,exists:function()/*.*/,className:”人类”);var person=Person.find();这样就可以给我们的Person类添加静态属性和方法了,现在是不是有点经典类的赶脚了。但是只能给Person类添加静态属性和方法还不够啊,还得能给类的实例添加属性和方法啊?对啊,我们来看一下include()函数。include()函数:工作原理也是一样的,区别在于不是将属性复制至类中,而是复制到类的原型中,这下就很了然了吧。var Person=new Class;Person.include(save: function()/*.*/,name:”张三”);到这里,是不是更有经典类的赶脚了啊。不过还没完,我们继续。不知道大家发现没有,其实这么做有一个十分美妙的地方,就是可以支持模块了。模块是可以重用的代码段,用这种方法可以实现各种继承,用来在类之间共享通用的属性。看下面的代码:var Animal=breast:function()/共享的函数var Cat=new Class;var Dog=new Class;Cat.include(Animal);Dog.include(Animal);var cat=new Cat;var dog=new Dog;现在cat和dog都具有了breast方法。到这里,经典类的赶脚就更强烈了。其实还没完,我们还可以做的更多,比如:如何给实例添加私有属性,如何给类库添加继承,如何控制类库作用域.可惜,本文篇幅有限(主要是笔者能力有限,嘿嘿还是藏起来吧)不能一一介绍,笔者只把一个初始的框架给搭出来,望各位大虾大牛能够继续延伸,尽快把续集给补上。Javascript 创建对象的三种方法及比较【转载+整理】/zh-CN/docs/JavaScript/Guide/Inheritance_and_the_prototype_chain本文内容 引入 构造函数创建对象 Object.create创建对象 极简主义法 封装 继承 私有属性和私有方法 数据共享引入近 20 年前,也就是 Javascript 诞生时(1995 年),它只是一种简单的网页脚本语言,像如果你忘记填写用户名,就跳出一个警告,当时的网速只有 28Kbps,这样简单的交互也让 Web 服务器做显然不合适。如今,Javascript 几乎无所不能,从前端到后端,各种匪夷所思、令人瞠目结舌的用途,程序员用它完成越来越庞大的项目,代码复杂度也在直线飙升。单个网页包含 10000 行 Javascript 代码,早就司空见惯。2010 年,一个工程师透露:Gmail 代码长度是 443000 行!图 1 Gmail 代码段编写和维护如此庞大复杂的代码,多年的工程实践表明必须使用模块化策略,而要采用模块化,主流做法是“面向对象编程”,它具有抽象,封装,多态和继承这四个特点。可 Javascript 是一种基于对象(object-based)的语言,你遇到的所有一切几乎都是对象,它结合(简单的)函数式语言和(简单的)面向对象语言的特点,但其语法不支持“类(class)”,无法直接使用面向对象编程。如果要把“属性”和“方法”,封装成一个对象,甚至要从原型对象生成一个实例对象。因此,程序员们探索如何用 Javascript 模拟“类”?很多文章在谈到“Javascript 模拟类”,但首先我个人认为这个说法很有误解,即便为“类”加了双引号。面向对象是基于类的语言,构建在两个不同实体的概念之上的:类和实例。而 Javascript 是基于原型的语言,它只有对象。新对象在初始化时以原型对象为模板获得属性。任何对象都可以指定其自身的属性,即可以创建时指定,也可以运行时指定。而且,任何对象都可以关联于并作为另一个对象的原型(prototype),从而允许后者共享前者的属性。要是这样的话,几乎没什么可比性。之所以说“Javascript 模拟类”,完全是为了强调如何用 Javascript 进行像面向对象那样的编程,毕竟面向对象编程是这么多年的工程实践已经证明了的,除此之外,这种说法造成的歧义和误解实在是太大了,尤其是对初学者来说。Javascript 是有设计缺陷,这多半是因为历史原因。就像其设计师Brendan Eich说的:“与其说我爱 Javascript,不如说我恨它。它是 C 语言和Self 语言一 夜 情的产物。十八世纪英国文学家约翰逊博士说得好:the part that is good is not original, and the part that is original is not good.(它的优秀之处并非原创,它的原创之处并不优秀)”。 设计过于仓促。Javascript 的设计仅仅用了十天,设计师只是为了向公司交差,本人并不愿意这样设计。而且其设计初衷,只是为了解决一些简单的网页互动,并没有考虑复杂应用的情况。 没有先例借鉴。Javascript 结合了函数式编程和面向对象编程的特点,是世界上唯一使用 Prototype 继承模型的语言。 标准化过早。1995 年 5 月设计计方案定稿;同年 10 月解释器开发成功;同年 12 月推向市场。1996 年 8 月微软强势介入,推出自己的脚本语言 Jscript。因为市场竞争,网景公司申请国际化,于 1998 年标准化。相比之下,C 语言问世将近 20 年之后,国际标准才颁布。在面向对象编程中,类(class)是对象(object)的模板。Javascript 语言虽然不支持“类”,但可以用一些变通的方法来模拟。本文总结了 Javascript 创建对象的三种方法,讨论每种方法的特点,并着重介绍了我眼中的最佳方法。能用适当的方式来创建对象是 Javascript 模块化的前提。这样,我们就可以封装属性和方法,并进一步模拟出面向对象编程中已经相当成熟的做法,如继承,接口,甚至是设计模式。构造函数创建对象在 Javascript 中,构造方法其实就是一个普通的函数。当使用 new 操作符来作用这个函数时,它就可以被称为构造方法(构造函数,Constructor),使用 this 和 prototype。该方法是经典方法。代码段一:function Cat() = 大毛;Ctotype.makeSound = function () alert(喵);var cat1 = new Cat();alert();alert(cat1. makeSound();该方法的缺点是,比较复杂,用到了 this 和 prototype,不便于编写和阅读,而且浪费内存。Object.create 创建对象为了解决“构造函数法”的缺点,更方便地生成对象,ECMAScript 5(目前通行第三版),提出了一个新的方法Object.create(),调用这个方法来创建一个新对象。新对象的原型就是调用 create方法时传入的第一个参数。代码段二:定义 Cat 对象,用 Object.create 创建,不用 newvar Cat = name: 大毛, makeSound: function () alert(喵); ;var cat1 = Object.create(Cat);alert();cat1.makeSound();目前,各大浏览器的最新版本(包括 IE9)都部署了这个方法。如果遇到老式浏览器,可以用下面的代码自行部署。代码段三:if (!Object.create) Object.create = function (o) function F() F.prototype = o;return new F();这种方法比“构造函数”简单,但是不能实现私有属性和私有方法,实例对象之间也不能共享数据,对面向对象的模拟不够全面。极简主义法荷兰程序员 Gabor de Mooij 提出了一种比 Object.create 更好的方法,他称这种方法为“极简主义法(minimalist approach)”,也是我推荐的方法。封装这种方法不使用 this 和 prototype,代码部署起来非常简单。它也是先用一个对象模拟“类”。在这个类里面,定义一个构造函数 createNew,用来生成对象实例。代码段四:var Cat = createNew: function () / some code here ;然后,在 createNew 函数,定义一个对象实例,把这个对象作为返回值。代码段五:var Cat = createNew: function () / some code here var cat = ; = 大毛; cat.makeSound = function () alert(喵); ; return cat; ;使用时,
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 外贸订单合同范本英文
- 航运数据应用价值-洞察与解读
- 医学影像技术操作流程指南
- 膳食因素对COPD焦虑抑郁的影响-洞察与解读
- 财务报表分析与风险防范实操指南
- 部编版一年级语文上册《语文园地八》教案
- 妙妙和喵喵的信教案【社会妙妙和喵喵的信教案】(2025-2026学年)
- 人教版七年级英语上册第六单元全单元教案
- 语文一年级下册《识字四》教案
- 玩一玩滚一滚教案
- 身份证前六位与省市县区对照表可直接存入数据库
- 工程洽商单(样本)及工程设计中标通知书
- 三菱HOPE电梯的故障码
- YC/T 145.2-2012烟用香精相对密度的测定
- JJG 875-2019数字压力计
- 量子信息与量子计算课件
- 基于Robotstudio机器人上下料工作站设计
- 制梁场制存梁台座检测方案
- 质性研究方法PPT通用课件
- 中线的用法(倍长中线法)分析
- 劳动法学课程教学大纲
评论
0/150
提交评论