- 浏览: 234725 次
- 性别:
- 来自: 武汉
文章分类
- 全部博客 (123)
- Struts1 (1)
- struts2 (3)
- 专业词汇解释 (1)
- oracle (1)
- javascript (19)
- ExtJS (14)
- jsp (5)
- webLogic (8)
- GXT (2)
- SSH (2)
- displayTag (3)
- 浏览器 (6)
- eclipse (6)
- tomcat (1)
- spring (3)
- J2SE (1)
- SVN (5)
- JBPM (1)
- jQuery (1)
- DWR (2)
- jfreechart (1)
- php (1)
- java组件 (1)
- JSTL (1)
- 操作系统(winXP) (3)
- 心得 (3)
- webservices (1)
- Hibernate (1)
- 工具 (2)
- Online Editor (2)
- 区别 (1)
- 职场技能 (1)
- 个人关注 (2)
- Android (7)
- Linux (7)
- HTML (1)
- 工作总结 (1)
- 笔记 (0)
最新评论
-
luoxiang183:
是啊,不对啊
jboss-as-7.1.1不兼容spring解决办法 -
liqiaoqiaoz:
按照你上面的改法不正确出现如下错误:13:49:55,759 ...
jboss-as-7.1.1不兼容spring解决办法 -
webczw:
不错,学习
Android通过http协议数据交互的两种方式 -
peng_hao1988:
...
Rational Rose -
gepangtsai:
再判断下:
if (grid) {
grid.setW ...
ExtJS GridPanel根据窗口大小自动变化插件
8.1 JavaScript面向对象编程
许多Web开发人员对JavaScript的了解仅仅停留在简单的表单数据操作,以及浏览器DOM对象的简单操作上,以达到一些数据验证和动态页面的效果。所以当要实现的功能比较复杂时,写出的代码就显得凌乱并且难以维护,更不用说实现一个基于JavaScript的UI框架了。事实上,JavaScript 提供了完善的机制来实现面向对象的开发思想。
本章假设读者已经了解面向对象思想的基本概念,熟悉对象、类、继承等基本术语。以此为基础,将重点介绍如何在 JavaScript 中使用面向对象的思想,包括实现的原理、机制和技巧。我们将使用JavaScript来实现以下面向对象特性:
¾ 对象、类;
¾ 封装;
¾ 多态;
¾ 继承。
1.对象
在JavaScript中创建一个对象非常简单,我们可以使用内建的Object对象来创建一个对象:
- var myObj=new Object; //创建一个名为myObj的对象
- myObj.name='sam'; //给myObj对象添加一个name属性,其值为sam
- myObj.age=28; //给myObj对象添加一个age属性,其值为28
- 我们也可以使用JSON(JavaScript Object Notation)[1] 来创建一个对象:
- var myObj={name:’sam’,age:28}
- //创建一个包含name属性值为sam,age属性值为28的对象
var myObj=new Object; //创建一个名为myObj的对象 myObj.name='sam'; //给myObj对象添加一个name属性,其值为sam myObj.age=28; //给myObj对象添加一个age属性,其值为28 我们也可以使用JSON(JavaScript Object Notation)[1] 来创建一个对象: var myObj={name:’sam’,age:28} //创建一个包含name属性值为sam,age属性值为28的对象
2.类
JavaScript不同于Java、C++、C#等面向对象语言,它通过构造函数和原型对象(prototype)来实现类的创建。为了创建一个类,还需要创建一个构造函数:
function Person(name,age){ this.name=name; this.age=age; }
这样我们就创建了一个构造函数(类),它包含两个属性:name和age。
- var sam=new Person('sam',28); //创建一个Person对象,name为sam,age为28
- 我们可以通过“.”运算符来访问它的属性:
- alert(sam.name); //输出结果为sam
- var bob=new Person('bob',30); //创建一个Person对象,name为bob,age为30
- alert(bob.age); //输出结果为30
var sam=new Person('sam',28); //创建一个Person对象,name为sam,age为28 我们可以通过“.”运算符来访问它的属性: alert(sam.name); //输出结果为sam var bob=new Person('bob',30); //创建一个Person对象,name为bob,age为30 alert(bob.age); //输出结果为30
细心的读者可能会发现,到目前为止,我们通过函数创建的对象只是封装了数据成员,并没有封装相应的方法。下面我们将在Person类中添加一个方法:
- function Person(name,age){
- this.name=name;
- this.age=age;
- this.introduceSelf=function(){
- alert('I am '+name+' , I am '+age +' years old.');
- }
- }
- var sam=new Person('sam',28);
- sam.introduceSelf() //输出结果为:I am sam,I am 28 years old
- var bob=new Person('bob',30);
- bob.introduceSelf() //输出结果为:I am bob,I am 30 years old
function Person(name,age){ this.name=name; this.age=age; this.introduceSelf=function(){ alert('I am '+name+' , I am '+age +' years old.'); } } var sam=new Person('sam',28); sam.introduceSelf() //输出结果为:I am sam,I am 28 years old var bob=new Person('bob',30); bob.introduceSelf() //输出结果为:I am bob,I am 30 years old
但是上面这种添加方法的方式不是很好。因为introduceSelf函数对于所有Person的实例来说,都是一样的,我们不希望在实例级别加上一个对于所有实例来说都一样的方法。这里我们要引入原型对象(prototype)的介绍。
每个JavaScript构造函数都有一个内部引用指向另一个称为原型对象(prototype)的对象。对于这个构造函数所产生的对象实例,该构造函数的原型对象所有属性对于它们来说都是可见的,并且是共享的。所以有时候也称该原型对象是这些实例的原型对象。对于这些实例,对原型对象的属性的访问方式和对自身的属性的访问方式是一致的。下面我们举例说明。
首先定义一个构造函数(类):
function Person(name,age){ this.name=name; this.age=age; }
然后,在函数的原型对象中添加一个属性kind:
- Person.prototype.kind='animal';
- 接着创建两个Person的实例:
- var p1=new Person('sam',28);
- var p2=new Person('bob',30);
- 访问这两个实例的kind属性:
- alert(p1.kind); //输出animal
- alert(p2.kind); //输出animal
Person.prototype.kind='animal'; 接着创建两个Person的实例: var p1=new Person('sam',28); var p2=new Person('bob',30); 访问这两个实例的kind属性: alert(p1.kind); //输出animal alert(p2.kind); //输出animal
通过上面的例子,我们可以看到函数的原型对象对于所有实例来说是共享的,并且属性的访问方式和实例本身的属性的访问方式完全一致。
如果修改这个属性,会怎么样呢?让我们接着往下看:
p1.kind='male'; alert(p1.kind); //输出male alert(p2.kind); //输出animal
这是怎么回事呢?原来对于原型对象的操作,读写是不对称的。通过实例对属性名的引用并不能修改原型对象属性的值,它只是在实例本身添加了一个和原型对象属性名一样的属性,并将该值赋给自身的那个属性。而对属性的访问,JavaScript首先会从对象本身开始查找,如果找到则返回该属性的值;如果没有找到,才会在其原型对象中查找。所以对于p1,当执行了p1.kind='male'之后,p1本身就有了一个kind属性,所以当再次访问p1的kind属性时,就会直接返回p1本身kind属性值“male”,而不是其原型对象里的值“animal”。
在了解了原型对象之后,我们再回到原来的例子。我们需要在构造函数Person的原型对象上添加一个方法,这样这个方法就会被所有的Person对象共享:
- Person.prototype. introduceSelf=function(){
- alert('I am '+this.name+' , I am '+this.age +' years old.');
- }
- var p1=new Person('sam',28);
- var p2=new Person('bob',30);
- p1.introduceSelf() //输出结果为:I am sam,I am 28 years old
- p2.introduceSelf() //输出结果为:I am bob,I am 30 years old
Person.prototype. introduceSelf=function(){ alert('I am '+this.name+' , I am '+this.age +' years old.'); } var p1=new Person('sam',28); var p2=new Person('bob',30); p1.introduceSelf() //输出结果为:I am sam,I am 28 years old p2.introduceSelf() //输出结果为:I am bob,I am 30 years old
3.多态
JavaScript允许我们将任意一个函数(function)分配给对象的一个属性。当使用 obj.function 的语法调用函数时,将把函数原来定义this 的指向当前这个对象obj(就像它在构造函数中的那样)。所以,我们可以通过定义有相同名字的方法的对象,来简单地实现多态性(polymorphism)。
- //定义一个dogSpeek函数
- function dogSpeek(){
- alert('I am '+this.name);
- }
- //定义一个Dog类
- function Dog(){
- this.name='dog';
- this.speek= dogSpeek;//将dogSpeek 函数赋给Dog的speek属性
- }
- //定义一个catSpeek函数
- function catSpeek(){
- alert('I am '+this.name);
- }
- //定义一个Cat类
- function Cat(){
- this.name='cat';
- this.speek= catSpeek; //将catSpeek ()函数赋给Cat的speek属性
- }
- var dog=new Dog;
- dog.speek();//输出“I am dog”
- var cat=new Cat;
- cat.speek();//输出“I am cat”
//定义一个dogSpeek函数 function dogSpeek(){ alert('I am '+this.name); } //定义一个Dog类 function Dog(){ this.name='dog'; this.speek= dogSpeek;//将dogSpeek 函数赋给Dog的speek属性 } //定义一个catSpeek函数 function catSpeek(){ alert('I am '+this.name); } //定义一个Cat类 function Cat(){ this.name='cat'; this.speek= catSpeek; //将catSpeek ()函数赋给Cat的speek属性 } var dog=new Dog; dog.speek();//输出“I am dog” var cat=new Cat; cat.speek();//输出“I am cat”
对于同一个方法,不同类的对象就展现出不同的行为,这样就实现了多态性。
4.继承
继承是面向对象开发的又一个重要概念,在JavaScript中通过原型链机制来实现类的继承,当然也可以通过将一个类的prototype拷贝到另外一个类来实现继承。
- function Base(x) // 定义一个父类
- {
- this.x = x;
- }
- Base.prototype.doIt = function() //在父类中添加一个方法
- {
- this.x += 1;
- }
- function Sub(x,y) //定义一个子类
- {
- Base.call(this,x); // 调用父类的构造函数(非必需)
- this.y = y;
- }
- Sub.prototype = new Base; // 将Sub的原型对象修改为Base的实例,这是实现继承的关键一步
- //因为Sub类的原型对象是由构造函数Base产生的,所以它的constructor属性是Base,
- //我们需要把它改成Sub
- Sub.prototype.constructor=Sub;
- var obj = new Sub(1,1);
- alert(obj.x); //输出1
- alert(obj.y); //输出1
- obj.doIt();
- alert(obj.x); //输出2
function Base(x) // 定义一个父类 { this.x = x; } Base.prototype.doIt = function() //在父类中添加一个方法 { this.x += 1; } function Sub(x,y) //定义一个子类 { Base.call(this,x); // 调用父类的构造函数(非必需) this.y = y; } Sub.prototype = new Base; // 将Sub的原型对象修改为Base的实例,这是实现继承的关键一步 //因为Sub类的原型对象是由构造函数Base产生的,所以它的constructor属性是Base, //我们需要把它改成Sub Sub.prototype.constructor=Sub; var obj = new Sub(1,1); alert(obj.x); //输出1 alert(obj.y); //输出1 obj.doIt(); alert(obj.x); //输出2
从上面的例子我们可以看到,Sub类的实例obj继承了Base类的属性x,以及方法doIt。
我们还可以通过拷贝父类中的方法来实现继承。
- function Inherit(superclass, subclass) {
- var from = superclass.prototype; // 父类的原型对象
- var to = subclass.prototype; // 子类的原型对象
- for(m in from) { //搜索原型对象中的所有属性
- if (typeof from[m] != "function") continue; // 忽略非函数
- to[m] = from[m]; // 拷贝方法
- }
- }
function Inherit(superclass, subclass) { var from = superclass.prototype; // 父类的原型对象 var to = subclass.prototype; // 子类的原型对象 for(m in from) { //搜索原型对象中的所有属性 if (typeof from[m] != "function") continue; // 忽略非函数 to[m] = from[m]; // 拷贝方法 } }
下面我们用这个函数来实现继承。
- function Base(x){
- this.x=x;
- }
- Base.prototype.doIt=function(){
- this.x+=1;
- }
- function Sub(x,y){
- Base.call(this,x);
- this.y=y;
- }
- Inherit(Base,Sub);
- var obj = new Sub(1,1);
- alert(obj.x); //输出1
- alert(obj.y); //输出1
- obj.doIt();
- alert(obj.x); //输出2
function Base(x){ this.x=x; } Base.prototype.doIt=function(){ this.x+=1; } function Sub(x,y){ Base.call(this,x); this.y=y; } Inherit(Base,Sub); var obj = new Sub(1,1); alert(obj.x); //输出1 alert(obj.y); //输出1 obj.doIt(); alert(obj.x); //输出2
通过上面的方式,同样实现了继承。对于第二种方式,说是继承并不严格,因为它只是借用Base类中的方法,它们之间没有真正的继承关系。我们可以使用instanceof方法来证明这一点。
对于第一种方式:
alert(obj instanceof Base); //输出true,说明Sub类对象是一个Base类的实例
对于第二种方式:
alert(obj instanceof Base); //输出false,说明Sub类对象不是一个Base类的实例
总结:JavaScript不同于Java、C++、C#等基于类的面向对象语言,它是基于原型对象的面向对象语言。它通过原型对象和构造函数可以很好地实现面向对象的开发,这为使用JavaScript开发大型的、复杂的程序提供了可能。
发表评论
-
JS 鼠标相对document的坐标以及HTML元素相对document的坐标
2010-11-09 09:10 1944Number.prototype.NaN0 = fun ... -
JS offset screen scroll client 介绍(IE)
2010-11-09 08:39 1907obj.offset[Width|Height|Top ... -
动态生成SQL查询语句
2010-07-30 16:35 1300<?xml version="1.0" ... -
javascript实现Table列的拖动
2010-04-15 10:38 1798<!DOCTYPE HTML PUBLIC " ... -
常用的JavaScript验证正则表达式
2009-12-04 09:47 768匹配中文字符的正则表达式: [u4e00-u9fa5]评注:匹 ... -
窗口刷新问题
2009-09-30 13:34 11941.用window.open()方法打开子窗口 在子窗口刷新 ... -
JavaScript,调用函数的5种方法
2009-09-12 16:11 1202一次又一次的,我发现, ... -
点击按钮把文本框的内容复制到剪切板的代码
2009-07-23 09:21 2094<input id="demo" ... -
在javascript文件中使用jstl标签
2009-07-16 09:40 2209天看到同事harry_duan写的一个js文件,感觉挺有意思。 ... -
javascript 创建类的几个方法
2009-07-04 14:33 1366Javascript 语言本身也可以进行面向对象的编程,如下是 ... -
Window.ShowModalDialog使用手册
2009-07-01 09:42 1207Window.ShowModalDialog使用手 ... -
window.opener.location.reload() and href()的区别
2009-07-01 09:04 14192个方法都是刷新父窗口,但是其中还是有奥妙的哦。 ... -
BOM IE浏览器对象模型 基本结构
2009-06-27 19:34 1431文档对象模型(DOM)属于VBScript客户端扩展部分,在文 ... -
Table表格对象
2009-06-27 19:33 931Table表格对象 Table对象 ... -
javaScript页面刷新(收藏)
2009-06-26 08:29 1245//--让打开本窗口的父页面重新刷新(在同一个窗口)--> ... -
function,new function,new Function对比
2009-06-17 15:57 1222函数是JavaScript中很重要 ... -
将阿拉伯数字翻译成中文的大写数字
2009-06-15 10:11 3299function Chinese(num) { if( ... -
用面向对象的方式封装javascript(Animal.js ,Bird.js,People.js)
2009-05-26 14:01 1320javascript 虽然是弱类型检查的脚本语言,可是它也有很 ...
相关推荐
在提供的资源中,《代码之美》PDF文件可能包含了关于编程实践和代码风格的指导,而《Javascript面向对象编程》PPT可能更具体地阐述了JavaScript OOP的细节和示例。学习这些材料将有助于深入理解JavaScript的面向对象...
JavaScript作为一门浏览器语言的核心思想;面向对象编程的基础知识及其在... 《JavaScript面向对象编程指南》着重介绍JavaScript在面向对象方面的特性,展示如何构建强健的、可维护的、功能强大的应用程序及程序库
《JavaScript面向对象编程指南》内容包括:JavaScript作为一门浏览器语言的..., 《JavaScript面向对象编程指南》着重介绍JavaScript在面向对象方面的特性,展示如何构建强健的、可维护的、功能强大的应用程序及程序库。
JavaScript是一种广泛...通过深入学习这本《JavaScript面向对象编程指南(第2版)》,开发者不仅能掌握JavaScript的面向对象编程基础,还能了解到实际项目中如何有效地运用这些知识,提升编程技巧和解决问题的能力。
### JavaScript面向对象编程详解 #### 一、引言 JavaScript作为一种广泛使用的脚本语言,在Web开发领域占据着举足轻重的地位。尽管JavaScript本质上是一种基于原型的语言,但它也支持面向对象编程的一些特性,使得...
总而言之,学习现代JavaScript面向对象编程,有助于开发者在认识这门语言演化的基础上,运用面向对象的设计和编程模式来构建更加健壮和可维护的JavaScript应用程序。同时,测试和调试是保证代码质量不可或缺的环节,...
下面将详细探讨JavaScript面向对象编程的基本原理、特性以及实际应用。 1. **类与对象** - 在JavaScript中,对象是键值对的集合,可以通过字面量语法或构造函数创建。例如: ```javascript const person = { ...
JavaScript面向对象编程指南是完整的扫描版...
javascript面向对象编程指南 2nd英文版,英文名:Object-Oriented JavaScript。 What you will learn from this book The basics of object-oriented programming, and how to apply it in the JavaScript ...
JavaScript面向对象编程.pdf
资源名称:Javascript面向对象编程 内容简介: 从语言的视角来看,面向对象的程序设计和面向对象的Javascript 语言绝对不是什么摩登的 东西;Javascript 最开始就是被设计成一...
JavaScript 面向对象 编程指南 完整扫描版