面向对象的编程思想在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 相关文章推荐
JQuery获取元素文档大小、偏移和位置和滚动条位置的方法集合
Jan 12 Javascript
Jquery Ajax学习实例7 Ajax所有过程事件分析示例
Mar 23 Javascript
js前台分页显示后端JAVA数据响应
Mar 18 Javascript
js中string转int把String类型转化成int类型
Aug 13 Javascript
jQuery的Ajax用户认证和注册技术实例教程(附demo源码)
Dec 08 Javascript
简单的JS时钟实例讲解
Jan 13 Javascript
JavaScript中最常见的三个面试题解析
Mar 04 Javascript
JS变量及其作用域
Mar 29 Javascript
浅谈vue项目如何打包扔向服务器
May 08 Javascript
JavaScript单线程和任务队列原理解析
Feb 04 Javascript
vue v-model的用法解析
Oct 19 Javascript
如何使用JavaScript策略模式校验表单
Apr 29 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可能遇到的问题“无法载入mysql扩展” 的解决方法
2007/04/16 PHP
判断php数组是否为索引数组的实现方法
2013/06/13 PHP
php文件上传的简单实例
2013/10/19 PHP
Codeigniter框架实现获取分页数据和总条数的方法
2014/12/05 PHP
php使用strip_tags()去除html标签仍有空白的解决方法
2016/07/28 PHP
php格式化时间戳
2016/12/17 PHP
php 后端实现JWT认证方法示例
2018/09/04 PHP
yii2.0框架实现上传excel文件后导入到数据库的方法示例
2020/04/13 PHP
php模拟实现斗地主发牌
2020/04/22 PHP
asp.net下使用jquery 的ajax+WebService+json 实现无刷新取后台值的实现代码
2010/09/19 Javascript
JavaScript中的object转换函数toString()与valueOf()介绍
2014/12/31 Javascript
js控制TR的显示隐藏
2016/03/04 Javascript
JavaScript限制在客户区可见范围的拖拽(解决scrollLeft和scrollTop的问题)(2)
2017/05/17 Javascript
微信小程序实现漂亮的弹窗效果
2020/05/26 Javascript
解决vue接口数据赋值给data没有反应的问题
2018/08/27 Javascript
浅谈Vue 性能优化之深挖数组
2018/12/11 Javascript
用node.js写一个jenkins发版脚本
2019/05/21 Javascript
[01:21]DOTA2 新英雄 森海飞霞
2020/12/18 DOTA
Python中利用sorted()函数排序的简单教程
2015/04/27 Python
python基于Tkinter库实现简单文本编辑器实例
2015/05/05 Python
PyQt5实现QLineEdit添加clicked信号的方法
2019/06/25 Python
一个非常简单好用的Python图形界面库(PysimpleGUI)
2020/12/28 Python
CSS3 网页下拉菜单代码解释 中文翻译
2010/02/27 HTML / CSS
用HTML5制作一个简单的桌球游戏的教程
2015/05/12 HTML / CSS
HTML5 虚拟键盘出现挡住输入框的解决办法
2017/02/14 HTML / CSS
意大利奢侈品网站:Italist
2016/08/23 全球购物
Gap加拿大官网:Gap Canada
2017/08/24 全球购物
海蓝之谜(LA MER)澳大利亚官方商城:全球高端奢华护肤品牌
2017/10/27 全球购物
一级方程式赛车官方网上商店:F1 Store(支持中文)
2018/01/12 全球购物
Calzedonia美国官网:意大利风格袜子、打底裤和沙滩装
2018/07/19 全球购物
奥地利购买珠宝和手表网站:ELLA JUWELEN
2019/09/03 全球购物
一月红领巾广播稿
2014/02/11 职场文书
工地宣传标语
2014/06/18 职场文书
会计系毕业求职信
2014/08/07 职场文书
青春飞扬演讲稿
2014/09/11 职场文书
JavaScript模拟实现网易云轮播效果
2022/04/04 Javascript