面向对象的编程思想在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 相关文章推荐
JSON 入门指南 想了解json的朋友可以看下
Aug 26 Javascript
JS版的date函数(和PHP的date函数一样)
May 12 Javascript
jquery中each方法示例和常用选择器
Jul 08 Javascript
javascript制作的cookie封装及使用指南
Jan 02 Javascript
jquery+ajax请求且带返回值的代码
Aug 12 Javascript
JS实现屏蔽网页右键复制及ctrl+c复制的方法【2种方法】
Sep 04 Javascript
AngularJS中关于ng-class指令的几种实现方式详解
Sep 17 Javascript
JS中数组重排序方法
Nov 11 Javascript
vue router自动判断左右翻页转场动画效果
Oct 10 Javascript
JavaScript使用prototype原型实现的封装继承多态示例
Aug 31 Javascript
详解单页面路由工程使用微信分享及二次分享解决方案
Feb 22 Javascript
JavaScript实现简易计算器小功能
Oct 22 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 strnatcmp()函数的用法总结
2013/11/27 PHP
PHP变量内存分配问题记录整理
2013/11/27 PHP
async和DOM Script文件加载比较
2014/07/20 PHP
php实现PDO中捕获SQL语句错误的方法
2017/02/16 PHP
实例分析基于PHP微信网页获取用户信息
2017/11/24 PHP
thinkPHP5框架分页样式类完整示例
2018/09/01 PHP
理解Javascript_13_执行模型详解
2010/10/20 Javascript
javascript实现倒计时并弹窗提示特效
2015/06/05 Javascript
JavaScript中的原型prototype完全解析
2016/05/10 Javascript
使用do...while的方法输入一个月中所有的周日(实例代码)
2016/07/22 Javascript
微信JS接口大全
2016/08/25 Javascript
JavaScript将base64图片转换成formData并通过AJAX提交的实现方法
2016/10/24 Javascript
AngularJS实现动态编译添加到dom中的方法
2016/11/04 Javascript
jQuery Validate验证表单时多个name相同的元素只验证第一个的解决方法
2016/12/24 Javascript
ES6新特性八:async函数用法实例详解
2017/04/21 Javascript
解决ie img标签内存泄漏的问题
2017/10/13 Javascript
jQuery+SpringMVC中的复选框选择与传值实例
2018/01/08 jQuery
浅析Vue实例以及生命周期
2018/08/14 Javascript
Jquery的Ajax技术使用方法
2019/01/21 jQuery
js实现移动端tab切换时下划线滑动效果
2019/09/08 Javascript
node.js +mongdb实现登录功能
2020/06/18 Javascript
OPENCV去除小连通区域,去除孔洞的实例讲解
2018/06/21 Python
python树莓派红外反射传感器
2019/01/21 Python
Django实现跨域的2种方法
2019/07/31 Python
python 回溯法模板详解
2020/02/26 Python
Python打印不合法的文件名
2020/07/31 Python
小女主人连衣裙:Little Mistress
2017/07/10 全球购物
无谷物狗粮:Pooch & Mutt
2018/05/23 全球购物
MIXIT官网:俄罗斯最大的化妆品公司之一
2020/01/25 全球购物
日本最大的购物网站乐天市场国际版:Rakuten Global Market(支持中文)
2020/02/03 全球购物
Lookfantastic阿联酋官网:英国知名美妆护肤购物网站
2020/05/26 全球购物
汇科协同Java笔试题
2012/03/31 面试题
英语分层教学实施方案
2014/06/15 职场文书
大学生个人学年总结
2015/02/15 职场文书
2016年习总书记讲话学习心得体会
2016/01/20 职场文书
再次探讨go实现无限 buffer 的 channel方法
2021/06/13 Golang