分享
 
 
 

再论面向对象的Javascript编程

王朝html/css/js·作者佚名  2006-01-08
窄屏简体版  字體: |||超大  

确实没有想到,第一次写一篇文章居然会上CSDN的头条,可能最主要的还是来自于hax那篇比较深刻的评论吧。我非常欣赏hax的才气,所以对于他的评论全盘照收,至于有些网友不是很满意他评论的风格,这个因人而异,我个人也就不做太多的评论.

再论面向对象的Javascript编程

——对于原文《面向。。。》的补充

作者:蓝翼

联系方式: liuruhong@263.net

关键字:Javascript OOP 面向对象 Jscript 原型 prototype

提要:

在原先《面向对象的JavaScript编程》中,笔者提出了通过Javascript(确切意义上面来说是Microsoft的Jscript)来实现OOP的思想,原文中因为笔者知识的局限,存在一些没有理清楚的思路,感谢一些网友提供的评论,结合这段时间的实际工作,笔者修正了原文中的一些想法.

因为个人知识水平有限的原因,以下所提到的JavaScript仅仅止于Microsoft 的Jscript,至于和NetScape之间的一些不同,也仅止于笔者所知道的范围。在原文中笔者提出了面向对象的JavaScript的概念,不是希望在卖弄Script的技巧,只是觉得在开发的过程中或多或少的会用到,因此从个人的角度提出一些相对可行性的建议。

原文对于Javascript提出了实现,封装,继承,重载,事件等等各个概念,因为个人理解的偏差,原文中有许多地方不甚贴切之处,因此本文只是对于原文的一些个人看法的一些修正。

Javascript从OOP的角度来说,应该不是一门纯OOP的语言,更加准确来说,是一门Object-Based的脚本语言,因此原文提到的所谓类的概念,只是从传统OOP语言的角度去描述的,而所谓的类实现,应该是一种原型实现方式,因为在整个实现的过程中prototype是一个最重要的体现。

理论上来说,所有的function都是object,因此类的创建可以完全基于Object来实现的,原文采用function只是为了更好的实现一些功能,以下就实现,封装,继承,重载,事件这5个概念作一些具体的阐述。

1. 实现。

Javascript的function是一等公民(hax原语),因此采用function来实现是最好的方式,至于采用如下两段代码来实现这个就是根据个人编程的习惯来决定,而一些实现的偏差我会在下文详细的描述。

代码1

function MyObject(sName){

this.name=sName;

this.MessageBox=function(){

alert("名字"+ this.name);

}

this.ChangeName=ChangeName;

function ChangeName(){

this.name="改变" + this.name;

}

}

代码2

function MyObject(sName){

this.name=sName;

}

MyObject.prototype.MessageBox=function(){

alert("名字"+ this.name);

}

MyObject.prototype.ChangeName=function(){

this.name="改变" + this.name;

}

采用标准的类实现结构和原型实现方式,在使用来说是没有区别的,如果从传统的类设计如(C++,smalltalk那样的语言)来说,应该采用第一种方案,但是就我个人而言,我建议使用第二种方案,毕竟在开发的过程中,那样的编写方式和Javascript的编写方式比较接近,基本立足于function的实现。

2.封装

既然引入了对象的概念,必然需要考虑到封装,C++这样的语言中有提出private ,protected,public的概念,在Javascript中,没有对应protected的概念,但是在private和public能够做到隐含的实现,另外如果需要大量使用到私有变量,实现方式中采用方案一可能更加合适一点,如下代码所示。

function MyObject(sName){

var mVar=1;

this.name=sName;

this.MessageBox=function(){

alert("名字"+ this.name);

mVar=2;

}

this.ChangeName=ChangeName;

function ChangeName(){

this.name="改变" + this.name;

}

this.GetVar=function(){

return mVar;

}

}

mVar是一个私有变量,name是一个共有变量,在MyObject内部实现的函数,可以访问mVar变量,而name则可以通过this.name的方式在任何实现的地方访问,对于内部函数的处理,ChangeName是不可以被直接访问的,但是可以通过Object.ChangeName()访问,这些概念在hax的评论中有几个网友讲述的比较详细.

简单而言,Javascript提供了对象中的private和public,但是并不提供显式声明,在类函数(姑且让我如此称呼)中定义的函数和变量都是私有变量,通过this.methodName或者this.varName定义的都是public实现的,通过object.prototype.name实现的也是public,在类函数中的私有函数可以访问那些私有变量和函数的,至于通过object.prototype.name那样实现的方法是否可以访问私有变量,我没有做过,如果谁做过,麻烦告诉我。

在VBS中提出了class的概念,如下的代码能够完整地体现封装的风格。

Class MyClass

Private vLoginID

Public UserName

Public Property Get LoginID

LoginID=vLoginID

End Propertyp

Public Property Let LoginID(vValue)

vLoginID=vValue

End Property

End Class

在Javascript中没有显式所谓属性概念,这点上面VBS的封装确实比较干净,JavaScript

中没有这样的概念,但是可以采用和Java类似的设计方法,如Get_PropertyName,Set_PropertyName这样的方法来做。我个人建议就采用函数来实现,如果如果带参数,则表示进行set操作,如果不带参数,可以认为是get操作。简单而言采用如下的代码风格。

Object.prototype.UserName=function(vValue){

If(vValue){

//todo get

}

Else{

Return value;

}

}

以上提及的只是我个人实现的观点。

3.继承

原文中提到通过设置原型的方式可以实现继承,就是通过SubObject.prototype=new BaseObject这样的方式来实现,至于对应的构造函数,在原文中采用了

This.base=parentclass;

This.base();

这样的方式实际是调用父类的构造函数来完成的,完成prototype(原型)设置之后,通过SubObject实例化的对象就可以访问父类的所有方法。在实际开发过程中碰到如下的问题,本来考虑到实现的时候通过方案一和方案二是没有任何区别的,可是如下的代码却有点奇怪。

function son(sName){

this.base=MyObject;

this.base(sName);

}

son.prototype.MessageBox=function(){

//this.base.MessageBox();

alert("子类调用");

}

son.prototype.hi=function(){

alert("kk");

}

var o=new son("hello");

o.MessageBox();

最后的执行结果是上文MyObject.MessageBox的方法,son.prototype.MessageBox这个函数却不执行,不清楚是否是我的代码还有问题,在继承方面,我发现通过this.method=functionName和object.prototype.methodName实现似乎不是完全一样的,对于这个方面如果有谁比较理解,麻烦告诉我。

在刚才的代码中不使用prototype就可以完成继承,这里采用的方法应该是构造函数初始化,因此Object.MessageBox等等一些函数都完全初始化,而如果没有写SubObject.prototype=BaseObject,那么BaseObject.prototype.methodName来实现的一些方法就无法实现。

4.重载

在原文中我提到使用Object.prototype.MethodName的方式来重写方法,但是同时保留了一个问题,就是如何调用父类的方法,上文提到的this.base=MyObject,this.base()这样只能够实现构造函数的实现的一些方法,也就是父类在函数体内本身定义的一些方法或者属性,通过原型prototype实现的就无法实现,在采用SubObject.prototype=new BaseObject那样的方式,也会出现一些上文提到的一些问题。

在Jscript 5.5以上版本,有一个call函数,通过这个函数我们可以完整的实现对于父类的方法调用,就如同Java里头的super,也就可以实现重载。如果读者的客户端系统是IE6或者WinME,就已经是Jscript5.5以上版本,至于XP或者2003我就不用多说了,Jscript引擎版本比较低的我建议下载高版本的。

BaseObject

-------------------

function BaseObject(){

this.msg=null

}

BaseObject.prototyp.Message(msg){

this.msg=msg;

alert(this.msg);

this.msg="change"+this.msg;

}

SubObject

function SubObject(){

BaseObject.call(this);

}

SubObject.prototype=new BaseObject;

SubObject.prototype.Message=function(msg){

BaseObject.prototype.Message.call(this,msg);

alert(this.msg);

}

调用代码

Var v= new SubObject();

v.Message(“hello”);

对于父类的方法通过call去调用,call(this,args)表示当前实例调用,在SubObject中,BaseObject.call(this)调用父类的方法,在重载Message函数的时候,为了维系原有的功能,首先调用父类的Message方法,然后才编写自己的实现代码。

从代码中大家可以明显看到是使用BaseObject.prototype.MethodName.call(this,args)这样的方法调用的,因为使用到了call函数,所以需要比较高版本的支持。

以上我讨论的是针对Jscript的实现,至于在别的引擎如NetScape或者Flash Script中,可以通过__proto__这个来返回父类的原型,因此调用上就简单许多,this._proto__相当于Java里头的super,在这里可以直接调用。

在低版本的Jscript引擎中我不知道是否可以通过instanceOf或者别的函数来共同实现,这也希望大家来共同探讨。

5.事件

本来,在OOP编程中,我不应该讨论如此的问题,但是在实际的应用中可能需要使用到类似事件的形式,因此在原文中,基本是采用了类似C++中虚函数的方法,不过在定义的时候只是使用了一个普通变量的方法。

如果类本身是和dom绑定的,对于HTML可以使用fireEvent函数来引发一些事件,不过这些应该已经属于DHTML讨论的东西了。

Javascript本身上来说没有所谓真正意义上面的面向对象,原文和本文提及的也只是正对实际开发工作中的一些逻辑实现,在浏览器内部确实不是适合大量的使用OOP的东西,但是对于Jscript Library开发人员来说,面向对象确实能够提供不少的好处,笔者写本文的目的也是希望能够对于Jscript Library的开发人员有说帮助,至少能够作为一个参考的资料。

因为本身水平有限,在一些的理解上面可能有些偏差,也希望有人能够给我指出来。

参考:

1. 面向对象的JavaScript编程(liuruhong原作)

http://www.csdn.net/develop/read_article.asp?id=19401

2. 评“面向对象的JavaScript编程”(hax原作)

http://www.csdn.net/develop/Read_Article.asp?Id=19485

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有