面向对象的编程思想在javascript中的运用上部


Posted in Javascript onNovember 20, 2009

其实,面向对象的思想是独立于编程语言的,例如在C#中,在一个静态类的静态方法中,按照过程式开发调用一系列静态函数,我们很难说这是面向对象的编程,相反,象jquery和extjs这样优秀的javascript库,却处处体现着面向对象的设计思想。本文不打算探讨javascript是否能够算做面向对象的编程语言,这个问题是重视中国式考试的人应该关注的,我这里只是简单的说明如何在javascript中使用面向对象的编程思想。
面向对象首先要有对象。在javascript中创建一个对象非常简单:

var o={};

这样就产生了一个对象,我们可以很方便的给这个对象添加属性和方法:
o.name="object name"; 
o.showName=function(){ 
alert(o.name); 
}

不过大多数人还是习惯把对象的属性和方法放在定义对象的一对{}里边:
var o = { 
name: "object name", 
showName: function() { 
alert(o.name); 
} 
}

访问属性和方法有两种方式,第一种:
alert(o.name); 
o.showName();

这种写法很常见,C#中调用对象的属性和方法也是这种方式。还有一种是javascript中比较特别的,使用属性或者方法的名字作为索引来进行访问:
alert(o["name"]); 
o["showName"]();

这好像有点和孔乙己“茴香的茴字有几种写法”差不多了,事实上,很少有人使用索引来调用对象的属性或者方法。
除了我们自定义的属性和方法,我们的对象还有一个constructor属性以及toString()等方法。这些属性和方法是从Object内置对象来的,所有的对象都会有这些属性和方法。其中constructor属性指向构造出该对象的构造函数。我们没有使用构造函数来创建对象,事实上,js的解释器会使用Object构造函数。如果我们自己定义了构造函数,那么便可以通过该构造函数来创建对象,这样可以使得创建的对象具有相同的属性和方法,这便开始有点面向对象的味道了。好,我们从一个简单的例子开始看看如何创建一个构造函数吧:
function Person(name, sex, age) { 
this.name = name; 
this.sex = sex; 
this.age = age; 
this.showInfo = function() { 
alert("姓名:" + this.name + " 性别:" + this.sex + " 年龄:" + this.age); 
} 
}

我们定义了一个名字叫Person的构造函数,该构造函数有三个属性和一个方法,通过构造函数来产生一个对象并调用方法也非常简单:
var zhangsan = new Person("张三", "男", 18); 
zhangsan.showInfo();

运行后我们可以看到弹出一个对话框,显示出这个叫张三的人的信息:
面向对象的编程思想在javascript中的运用上部
我们还可以看看对象的constructor属性来看看zhangsan的构造函数是不是我们定义好的Person:
alert(zhangsan.constructor);

结果如图:
面向对象的编程思想在javascript中的运用上部
可以看到,正是我们的Person构造函数。
不过,这里还是有点问题,每一次我们构造一个对象,都会在内存中为属性和方法分配内存空间,而事实上,所有的对象完全可以用同一个方法,并不需要有多个方法的副本,这样有些浪费内存空间。既然意识到了这个问题,让我们来想想如何解决吧。一个很自然的想法是,既然我们只想为方法分配一次内存空间,那么我们可以设置一个值用来标识方法的内存空间是否已经分配,按照这个思路,我们将构造函数做如下修改:
function Person(name, sex, age) { 
this.name = name; 
this.sex = sex; 
this.age = age; 
if (typeof Person._initialized == "undefined") { 
this.showInfo = function() { 
alert("姓名:" + this.name + " 性别:" + this.sex + " 年龄:" + this.age); 
} 
Person._initialized = true; 
} 
}

这里,我们用一个成员_initialized来指示是否已经对方法进行了内存空间的分配。当第一个对象构造的时候_initialized未被定义,所以我们的判断语句为真,这时会对方法进行了定义并分配内存空间,然后把_initialized的值设置为true,用以表明方法的内存空间已经分配了。第二个对象构造的时候则不会再进入判断,因而也不会再一次分配内存空间。似乎没什么问题,运行一下看看,张三的信息依然正常显示。虽然不辛苦,不过解决了一个小问题,还是庆祝下吧,来盘回锅肉,我要大快朵颐。还没开吃,一个叫李四的MM也想让电脑弹出她的个人信息。OK,很简单,再构造一个对象,然后调用showInfo方法就可以了:
var lisi = new Person("李四", "女", 28); 
lisi.showInfo();

为了照顾MM,还把这段放在了张三的前边。MM的信息正确显示出来了,可是张三的资料不见了。这下张三不乐意了,排名放在MM后边也罢了,但好歹得有名字啊。这可苦了我这编程人员,回锅肉看来没办法吃了,先改bug吧。打开firebug,看到MM的信息显示之后出现错误,提示为:zhangsan.showInfo is not a function。设置断点看看,构造zhangsi对象以后发现并没有showInfo这个方法。原来showInfo方法虽然只有一个,但是存在于第一个对象之中,第二个对象并不能访问。那么,究竟如何才能让同一个构造函数产生的对象共用同一个函数呢?javascript中的prototype给我们提供了这个功能。根据javascript的规范中描述,每一个构造函数都有一个prototype属性用于实现继承和属性的共享。我们的showInfo方法也可以看作是一个属性,该属性指向一个函数的引用。现在我们使用prototype来使得我们的方法可以共享,代码的改动很简单,把this.showInfo改成Person.prototype.showInfo就可以了,改动之后的代码如下:
function Person(name, sex, age) { 
this.name = name; 
this.sex = sex; 
this.age = age; 
if (typeof Person._initialized == "undefined") { 
Person.prototype.showInfo = function() { 
alert("姓名:" + this.name + " 性别:" + this.sex + " 年龄:" + this.age); 
} 
Person._initialized = true; 
} 
}

使用该构造函数生成两个对象:
var lisi = new Person("李四", "女", 28); 
lisi.showInfo(); 
var zhangsan = new Person("张三", "男", 18); 
zhangsan.showInfo();

运行之后先显示李四的信息,然后是张三的信息。现在两个人都满意了,可惜我的回锅肉已经凉了
Javascript 相关文章推荐
JS中批量给元素绑定事件过程中的相关问题使用闭包解决
Apr 15 Javascript
javascript-表格排序(降序/反序)实现介绍(附图)
May 30 Javascript
JavaScript生成随机字符串的方法
Mar 19 Javascript
jQuery网页选项卡插件rTabs用法实例分析
Aug 26 Javascript
BootStrap和jQuery相结合实现可编辑表格
Apr 21 Javascript
轻松掌握jQuery中wrap()与unwrap()函数的用法
May 24 Javascript
jQuery实现判断上传图片类型和大小的方法示例
Apr 11 jQuery
详解vue-cli下ESlint 配置说明
Sep 03 Javascript
vue.js中使用echarts实现数据动态刷新功能
Apr 16 Javascript
通过循环优化 JavaScript 程序
Jun 24 Javascript
JavaScript动态添加数据到表单并提交的几种方式
Jun 26 Javascript
JS localStorage存储对象,sessionStorage存储数组对象操作示例
Feb 15 Javascript
javascript 设置文本框中焦点的位置
Nov 20 #Javascript
ExtJS Grid使用SimpleStore、多选框的方法
Nov 20 #Javascript
Jquery中增加参数与Json转换代码
Nov 20 #Javascript
ExtJS的FieldSet的column列布局
Nov 20 #Javascript
页面版文本框智能提示JS代码
Nov 20 #Javascript
js url传值中文乱码之解决之道
Nov 20 #Javascript
js trim函数 去空格函数与正则集锦
Nov 20 #Javascript
You might like
php中DOMElement操作xml文档实例演示
2013/03/26 PHP
十个PHP高级应用技巧果断收藏
2015/09/25 PHP
利用PHP如何写APP接口详解
2016/08/23 PHP
AJAX架构之Dojo篇
2007/04/10 Javascript
JQUERY 对象与DOM对象之两者相互间的转换
2009/04/27 Javascript
JavaScript 保存数组到Cookie的代码
2010/04/14 Javascript
浅析JS刷新框架中的其他页面 && JS刷新窗口方法汇总
2013/07/08 Javascript
jQuery插件slider实现拖动滑块选取价格范围
2015/04/30 Javascript
JS随机洗牌算法之数组随机排序
2016/03/23 Javascript
JavaScript必知必会(三) String .的方法来自何方
2016/06/08 Javascript
jquery easyUI中ajax异步校验用户名
2016/08/19 Javascript
JavaScript学习笔记整理_setTimeout的应用
2016/09/19 Javascript
详解nodejs 文本操作模块-fs模块(二)
2016/12/22 NodeJs
vue2 中如何实现动态表单增删改查实例
2017/06/09 Javascript
AngularJS自定义过滤器用法经典实例总结
2018/05/17 Javascript
使用vue的transition完成滑动过渡的示例代码
2018/06/25 Javascript
JavaScript设计模式之观察者模式(发布订阅模式)原理与实现方法示例
2018/07/27 Javascript
利用Node.js如何实现文件循环覆写
2019/04/05 Javascript
Vue实现搜索结果高亮显示关键字
2019/05/28 Javascript
[01:01:52]DOTA2-DPC中国联赛正赛 iG vs LBZS BO3 第一场 3月4日
2021/03/11 DOTA
Python列表append和+的区别浅析
2015/02/02 Python
python将ip地址转换成整数的方法
2015/03/17 Python
Python中实例化class的执行顺序示例详解
2018/10/14 Python
浅谈Django中的QueryDict元素为数组的坑
2020/03/31 Python
python3 googletrans超时报错问题及翻译工具优化方案 附源码
2020/12/23 Python
北美领先的牛仔品牌:Buffalo David Bitton
2017/05/22 全球购物
印度首个本地在线平台:nearbuy
2019/03/28 全球购物
南非最大的在线时尚商店:Zando
2019/07/21 全球购物
新西兰第一的行李箱网站:luggage.co.nz
2019/07/22 全球购物
保险公司演讲稿
2014/09/02 职场文书
先进党支部申报材料
2014/12/24 职场文书
检讨书范文500字
2015/01/28 职场文书
安全保证书怎么写
2015/02/28 职场文书
心理健康教育主题班会
2015/08/13 职场文书
2016年党员创先争优公开承诺书
2016/03/25 职场文书
MySQL数据库Innodb 引擎实现mvcc锁
2022/05/06 MySQL