JavaScript 面向对象编程(2) 定义类


Posted in Javascript onMay 18, 2010

本文承接上一篇JavaScript面向对象编程(1) 基础。
上篇说过,JavaScript没有类的概念,需要通过函数来实现类的定义。先通过一个例子说明:

function myClass() 
{ 
var id = 1; 
var name = "johnson"; 
//properties 
this.ID = id; 
this.Name = name; 
//method 
this.showMessage = function() 
{ 
alert("ID: " + this.ID + ", Name: " + this.Name); 
} 
} 
var obj1 = new myClass(); 
var obj2 = new myClass();

function的定义实际上相当于类的构造函数,最后两句是创建这个类的实例。先分析第一句:var obj1 = new myClass(); 当用new创建类的实例时,解释器首先会创建一个空的对象。然后运行这个myClass函数,并将this指针指向这个类的实例。当碰到this.ID = id;和this.Name = name;及this.showMessage = function(){...}时,便会创建这两个属性,和这个方法,并把变量id,name的值一级函数的定义赋给这两个属性及这个函数对象(shwoMessage)。这个过程相当于初始化这个对象,类似于C# 中的构造函数。最后new返回这个对象。再看第二句:var obj2 = new myClass(); 执行过程与上一句代码相同,即创建一个空对象,然后执行myClass这个函数,定义两个属性和一个方法。
从上面的分析中可以看到,上面这种实现类的方式,即在函数的定义中定义类的属性方法。存在着弊端。如果需要创建两个或更多这个类的实例时,上文是两个,这些属性会被重复的创建多次。
那么如何避免这种情况呢?上一篇中也曾提到过用prototype。prototype和它的名字一样是一个原型,每一个function都有一个子对象prototype,它其实表示这个function对象的成员的集合,由于这里我们使用function实现类的,所以可以说prototype其实就是便是类的成员的集合。prototype定义的属性和方法执行在函数的构造体执行之前,所以当new一个对象之前,其实prototype的成员已经执行过了。先看一个例子:
function myClass() 
{ 
//构造函数 
} 
myClass.prototype = 
{ 
ID: 1, 
Name: "johnson", 
showMessage: function() 
{ 
alert("ID: " + this.ID + ", Name: " + this.Name); 
} 
} 
var obj1 = new myClass(); 
var obj2 = new myClass();

类的结构还是和前面的例子相同,只不过这里是利用了prototype来实现。还是先看最后两句,前面说过,prototype是执行在函数构造体之前,即执行到var obj1 = new myClass();之前,这个类已经有了ID,Name属性和showMessage方法。执行者一句时执行过程如下,注意和前一个例子比较:首先还是创建一个空的对象,并把this指针指向这个对象。然后将函数的prototype对象的所有成员都赋给这个对象(注意没有再创建这些成员)。然后执行函数体。最后new返回这个对象。执行下一句时:同样执行此过程,不会重复创建这些成员。
上面的代码还只是一个例子,在实际的项目中,可能出现的是类中有大量的成员,同时可能需要创建大量的实例。这是prototype就会显示其优越性了。另外上面的代码中使用了大括号语法定义了prototype的成员,这样看起来代码更清晰。这是一种比较推荐的类的设计模式。当然在众多的项目中,可能还会发现更好的模式,我们也希望能有更优化的JavaScript的编程模式不断推陈出新,也希望随着时间的推移,各主流浏览器也对JavaScript的解析都标准,统一。
上面说过prototype定义的成员是发生在构造体之前,可以证明一下,在上面的例子中,构造体是空的,在构造函数中加入一句alert(this.Name);,当执行到var obj1 = new myClass();时,会看到弹出对话框,显示正确的属性值。
写了这段文字之后承蒙多为兄弟的点评,收获匪浅。对上面的例子进一步讨论,如下代码:
function subClass(){ } 
subClass.prototype = 
{ 
Name: "sub" 
} 
function myClass() 
{ 
//构造函数 
} 
myClass.prototype = 
{ 
ID: 1, 
Name: "johnson", 
SubObj: new subClass(), 
showMessage: function() 
{ 
alert("ID: " + this.ID + ", Name: " + this.Name + "SubObj.Name:" + this.SubObj.Name); 
} 
} 
var obj1 = new myClass(); 
obj1.SubObj.Name = "XXX"; 
obj1.showMessage(); 
var obj2 = new myClass(); 
obj2.showMessage();

这里在myClass中定义了一个引用类型,其类型是我们自定义的一个subClass类,这个子类中有一个Name属性。由于prototype对象是共享的,按照我们上面的分析:在执行var obj1 = new myClass();时,会把myClass的prototype中的成员复制给这个obj1实例。但这里SubObj是一个引用类型,在执行到var obj2 = new myClass();时,prototype中的ID,Name成员会复制到obj2中,但SubObj这个属性不会复制过去,而是引用了prototype中的SubObj,所以因为上一句修改了obj1.Subobj.Name的值,所以在用new生成obj2实例时,引用到了修改后的值。
所以借用prototype定义类时,依然需要将属性定义在构造体中,而将方法定义在该构造体的原型上。如下:
function myClass(id, name) 
{ 
this.ID = id; 
this.Name = name; 
} 
myClass.prototype = 
{ 
showMessage: function() 
{ 
alert("ID: " + this.ID + ", Name: " + this.Name); 
}, 
showMessage2: function() 
{ 
alert("Method2"); 
} 
} 
var obj1 = new myClass(1, "johnson"); 
obj1.showMessage(); 
obj1.Name="John"; 
obj1.showMessage(); 
var obj2 = new myClass(2, "Amanda"); 
obj2.showMessage();

关于私有成员,共有成员以及静态成员,类的继承,抽象类,虚方法,类的反射等实现方法,以后还会坚持写下去。不过我觉得需要说一下的是,我打算写的是JavaScript面向对象的基础实现,如果需要深入的学习建议参考李战老哥的“甘露模型”。
Javascript 相关文章推荐
jquery插件开发方法(初学者)
Feb 03 Javascript
js操作table示例(个人心得)
Nov 29 Javascript
javascript框架设计之框架分类及主要功能
Jun 23 Javascript
asp.net+jquery.form实现图片异步上传的方法(附jquery.form.js下载)
May 05 Javascript
JavaScript检测原始值、引用值、属性
Jun 20 Javascript
AngularJs Understanding the Controller Component
Sep 02 Javascript
EditPlus中的正则表达式 实战(2)
Dec 15 Javascript
使用 Node.js 开发资讯爬虫流程
Jan 07 Javascript
node全局变量__dirname与__filename的区别
Jan 14 Javascript
vue调用语音播放的方法
Sep 27 Javascript
在vue-cli3中使用axios获取本地json操作
Jul 30 Javascript
Javascript基于OOP实实现探测器功能代码实例
Aug 26 Javascript
JavaScript 面向对象编程(1) 基础
May 18 #Javascript
Javascript Object.extend
May 18 #Javascript
Jsonp 跨域的原理以及Jquery的解决方案
May 18 #Javascript
javascript 密码强度验证规则、打分、验证(给出前端代码,后端代码可根据强度规则翻译)
May 18 #Javascript
JS request函数 用来获取url参数
May 17 #Javascript
asp.net+js 实现无刷新上传解析csv文件的代码
May 17 #Javascript
JQuery中的ready函数冲突的解决方法
May 17 #Javascript
You might like
一个简洁的PHP可逆加密函数(分享)
2013/06/06 PHP
CI框架实现cookie登陆的方法详解
2016/05/18 PHP
解决tp5在nginx下修改配置访问的问题
2019/10/16 PHP
php使用goto实现自动重启swoole、reactphp、workerman服务的代码
2020/04/13 PHP
csdn 批量接受好友邀请
2009/02/19 Javascript
一些常用的JS功能函数(2009-06-04更新)
2009/06/04 Javascript
基于jquery扩展漂亮的下拉框可以二次修改
2013/11/19 Javascript
AngualrJS中每次$http请求时的一个遮罩层Directive
2016/01/26 Javascript
bootstrap实现的自适应页面简单应用示例
2017/03/09 Javascript
nodejs socket实现的服务端和客户端功能示例
2017/06/02 NodeJs
基于JavaScript实现无缝滚动效果
2017/07/21 Javascript
Angularjs的$http异步删除数据详解及实例
2017/07/27 Javascript
js中数组常用方法总结(推荐)
2019/04/09 Javascript
微信小程序bindinput与bindsubmit的区别实例分析
2019/04/17 Javascript
关于AOP在JS中的实现与应用详解
2019/05/06 Javascript
Vue-cli3.X使用px2 rem遇到的问题及解决方法
2019/08/08 Javascript
jQuery实现的上拉刷新功能组件示例
2020/05/01 jQuery
vue使用better-scroll实现滑动以及左右联动
2020/06/30 Javascript
[01:29:42]Liquid vs VP Supermajor决赛 BO 第一场 6.10
2018/07/05 DOTA
解决windows下Sublime Text 2 运行 PyQt 不显示的方法分享
2014/06/18 Python
Python实现的简单发送邮件脚本分享
2014/11/07 Python
Python 如何优雅的将数字转化为时间格式的方法
2019/09/26 Python
python实现从wind导入数据
2019/12/03 Python
Python3爬虫关于识别点触点选验证码的实例讲解
2020/07/30 Python
关于Java String的一道面试题
2013/09/29 面试题
opencv实现图像几何变换
2021/03/24 Python
安全生产检查通报
2014/01/29 职场文书
法制报告会主持词
2014/04/02 职场文书
网吧七夕活动策划方案
2014/08/31 职场文书
关于教师节的演讲稿
2014/09/04 职场文书
家庭贫困证明范本(经典版)
2014/09/22 职场文书
2015年清明节演讲稿范文
2015/03/17 职场文书
加班费申请报告
2015/05/15 职场文书
2016教师暑期培训学习心得体会
2016/01/09 职场文书
为什么RedisCluster设计成16384个槽
2021/09/25 Redis
MySQL实现字段分割一行转多行的示例代码
2022/07/07 MySQL