在Ajax的应用开发中,需要编写大量的JavaScript代码,如后面介绍的DWR和Dojo框架中使用了大量的JavaScript代码,这就对JavaScript程序设计提出了新的要求,很多Ajax 应用开始利用JavaScript 面向对象的性质进行开发,JavaScript提供了完善的机制来实现面向对象的设计思想。
4.1 JavaScript面向对象
4.1.1 JavaScript类的定义
在面向对象的程序设计中,最核心的概念之一就是类。一个类表示了具有相似性质的一类事物的抽象,通过实例化一个类,可以获得属于该类的一个实例(即对象)。
在JavaScript中定义一个类的方法如下:
function Helloclass(){
alert(“类的定义”);
//在这里可定义类成员的定义及构造函数
}
上面定义的Helloclass既是一个类成员的定义及构造函数数也是一个类。如果看作是函数,可以把它理解为类的构造函数,负责初始化的工作。
可以应用new操作符来创建一个对象,例如:
new Date();
上面的代码表示创建一个日期对象,而Date 就是表示日期的类,但是这个类是由JavaScript 内部提供的,而不是由用户定义的。用new 操作符可以创建用户定义的类,对于上面定义的Helloclass,也可以用new来生成一个对象:
function Helloclass (){
//定义类成员的定义及构造函数
}
var obj=new Helloclass ();
在JavaScript中,每个对象可以看作是多个属性(方法)的集合,引用一个属性(方法)的格式如下:
对象名.属性(方法)名
除此之外,还可以用方括号的形式来引用:
对象名[“属性(方法)名”]
这里所指的方法名和属性名是一个字符串,例如:
var arrs=new Array();
arrs[“push”](“tfnew21”); //添加一个元素
var lens=arrs[“length”]; //获得数组的长度
alert(lens);
上面编写的代码等价于如下代码:
var arrs=new Array();
arrs.push( “tfnew21”); //添加一个元素
var lens=arrs.length; //获得数组的长度
alert(lens);
上面这种引用属性(方法)的方式和数组类似,也反应出一个JavaScript对象就是一组属性(方法)的集合这个性质。
用方括号的形式来引用这种用法适合于不确定具体要引用哪个属性(方法)的应用,例如有一个用于表示用户资料的对象,通过一个字符串来表示要使用的属性,就可以用这种方式来引用,例如:
<script language="JavaScript" type="text/javascript">
<!--
//定义了一个User 类,包括三个属性name、age和sex,并指定了初始值。
function User(){
this.name=”tfnew21”;
this.age=18;
this.sex="男";
}
//创建user 对象
var user=new User();
//根据下拉列表框显示用户的信息
function show(slt){
if(slt.selectedIndex!=0){
alert(user[slt.value]);
}
}
//-->
</script>
<!--选择用户信息-->
<select οnchange="show(this)">
<option value="name">姓名</option>
<option value="age">年龄</option>
<option value="sex">性别</option>
</select>
在上面程序中,使用一个下拉列表框让用户选择User类的属性,每个选项的value就表示用户对象的属性名称。
4.1.2 prototype对象
prototype对象是实现面向对象的一个重要机制。每个函数(function)其实也是一个对象,它们对应的类是“Function”,每个函数对象都具有一个子对象prototype。prototype表示了该函数的原型,而函数也可以理解为是类,prototype表示了一个类的属性的集合。当通过new 来生成一个类的对象时,prototype 对象的属性都会成为实例化对象的属性。
下面以一个例子来介绍prototype 的应用,例子代码如下:
//定义了一个空类
function Helloclass(){
}
//对类的prototype对象进行修改,增加方法method
Helloclass.prototype.method=function(){
alert(“prototype测试”);
}
var obj=new Helloclass();//创建类Helloclass的实例
obj.method();//调用obj的方法method
当用new创建一个function时,该对象的属性将自动赋给所创建的对象,例如:
<script language="JavaScript" type="text/javascript">
<!--
//定义一个只有一个属性prop的类
function Helloclass(){
this.name=”tfnew21”;
}
//使用函数的prototype属性给类定义新属性
Helloclass.prototype.showName=function(){
alert(this.name);
}
var obj=new Helloclass();//创建Helloclass的一个实例
//调用通过prototype原型对象定义的showName方法
obj.showName();
//-->
</script>
因为prototype 是一个JavaScript 对象,所以可以为prototype 对象添加、修改方法和属性。
4.1.3 JavaScript反射机制
反射机制是指程序在运行期间能够获取自身的信息。例如一个对象能够在运行时知道自己拥用哪些方法和属性。在C#和Java都提供了反射机制,能够在运行时动态判断和调用自己的属性或方法。在JavaScript中用for(…in…)语句来实现反射,其语法如下:
for(var vs in obj){
if(typeof(obj[vs]==”function”){
obj[vs]();
}else{
alert(obj[vs]);
}
}
在上面的程序中var vs声明一个变量用来存储对象obj的属性(方法)名称,有了对象名和属性(方法)名,就可以使用方括号语法来调用一个对象的属性(方法)。
上面的程序语句实现遍历obj对象的所有属性和方法,遇到属性则显示它的值,遇到方法则立刻执行。该语句就是遍历一个集合内的所有成员。在面向对象的JavaScript程序设计中,反射机制是很重要的一种技术,它在实现类的继承中发挥了很大的作用。
4.1.4 反射机制在Ajax中的应用
在Ajax应用编程中,经常需要能动态改变界面元素的样式,这可以通过对象的style属性来改变,比如要改变背景色为红色,可以这样写:
element.style.backgroundColor=”#000000”;
其中style 对象有很多属性,一般在CSS 里拥有的属性在JavaScript 中都能够调用。现在如果用一个函数接收参数,用以指定一个界面元素的样式,那就需要设计参数的实现方式,显然一个或几个参数是不能符合要求的,下面是实现方式之一:
function setStyle(_style){
var element=getElement();//得到要改变样式的界面对象
element.style=_style;
}
这样,直接将整个style对象作为参数,一个style对象可能的形式如下:
var style={
color:#ffff00,
backgroundColor:#ff0cc0,
borderWidth:1px,
width:100px
}
在程序中调用函数的方法为:
setStyle(style);
上面这段代码看上去没有任何问题,但实际上,在setStyle 函数内部使用参数_style 为
element.style赋值时,如果element 原先已经有了一定的样式,例如曾经执行过:
element.style.width=”100px”;
而_style 中却没有包括对width 的定义,因此element 的width样式就丢失了。要解决这个问题,可以用反射机制来重写setStyle函数,实现方法如下:
function setStyle(_style){
var element=getElement();//得到要改变样式的界面对象
for(var p in _style){
element.style[p]=_style[p];
}
}
上面程序实现遍历_style 的每个属性,得到属性名称,然后再使用方括号语法将element.style中的对应的属性赋值为_style 中的相应属性的值。从而,element 中仅改变指定的样式,而其他样式不会改变,得到了所要的结果。