JavaScript作为一种脚本开发语言,由于其语法简洁灵活,功能强大,已经被开发人员广为接受。虽然JavaScript 支持面向对象开发(OOP),但与我们通常所熟悉的面向对象开发语言,如Java、C++等,在类和对象的语法定义上有很大的区别,在Java、C++等面向对象的开发语言中定义类和对象非常直观,如在Java语言中定义类:
{
//属性定义
private String str;
private int i;
//方法定义
public void test() {
System.out.println("test");
}
}
//定义实例对象
A a = new A();
而在JavaScript中类的定义与一般函数的定义是一样的:
function A() {
//属性定义
this.str = "test";
this.i = 0;
}
//方法定义
A.prototype.test = function() {
alert(this.str);
}
//对象实例定义
var a = new A();
a.test();
在表现形式上不太直观,而且容易让人与一般功能函数产生混淆。
笔者根据平时的一点开发经验和体会,在现有JavaScript语法的基础上,向大家介绍一种更直观的类定义方法。
一、JxObject类
为了支持新的类定义形式,笔者先定义了一个JxObject类来提供一些必要的方法支持,其代码如下:

/**//******************************
* JxObject.js
* created on 2007-04-23
*******************************/
//
//--- JxObject class ----------------------------------
//
function JxObject() ...{
}
//类定义方法
JxObject.defineClass = function(clsBody) ...{
var cls = new Function();
cls.prototype = (new JxObject()).extended(clsBody);
cls.__getInstance = function() ...{
return new cls();
};
cls.getInstance = function() ...{
var newObj = cls.__getInstance();
if(newObj.init != null && typeof newObj.init == 'function') ...{
newObj.init.apply(newObj, arguments);
}
return newObj;
};
var __superTargetObj = cls.__getInstance();
cls.__getSuperTargetObj = function() ...{ return __superTargetObj; };
return cls;
}
//类继承方法
JxObject.inherits = function(targetCls, clsBody) ...{
var targetObj = targetCls.__getInstance();

targetObj.__super = function(__superClass, fname) ...{
var __superObj = __superClass.__getSuperTargetObj();
if(typeof __superObj[fname] != 'undefined' && __superObj[fname] != null
&& typeof __superObj[fname] == 'function') ...{
var args = new Array();
for(var i=2; i<arguments.length; i++) ...{
args[i-2] = arguments[i];
}
return __superObj[fname].apply(this, args);
}
};
var cls = JxObject.defineClass(clsBody);
cls.prototype = targetObj.extended(clsBody);
return cls;
}

JxObject.prototype.extended = function(targetObj) ...{
return JxObject.__extends.apply(this, [this, targetObj]);
}

JxObject.__extends = function(targetObj, parentObj) ...{
for(var i in parentObj) ...{
targetObj[i] = parentObj[i];
}
return targetObj;
}

在JxObject类中定义了两个非常重要的方法:defineClass和inherits,对于这两个方法的使用将在下面逐一介绍。
二、类的定义
有了JxObject类中的defineClass方法的支持,我们可以在JavaScript中这样来定义类:
//属性定义
name : "",
age : 0,
//方法定义
init : function(name, age) {
this.name = name;
this.age = age;
},
sayHello : function() {
alert("Hello, I'm " + this.name + ", my age is " + this.age + ". "
+ "And I'm so glad to know you!");
}
});
var mike = Person.getInstance('Mike', 20);
mike.sayHello();
var jack = Person.getInstance('Jack', 30);
jack.sayHello();
从上例中我们可以看到,defineClass方法的参数为一个临时对象,用来包含当前要定义的类的方法和属性,通过这样的定义形式,类的定义变得比较直观了,类的实例变量不再需要用new操作符来生成,而是通过调用在类中定义的getInstance方法来生成,而且,如果需要对实例变量进行初始化,只需要在类的定义中定义一个init(arg1,arg2,...)方法就可以了,当通过调用getInstance方法获得类的实例变量时,该方法将被自动调用。
三、类的继承
在前面的例子中,我们看到了类定义的方法,现在让我们来看看怎样从现有的类继承产生子类,先看下面的例子:

var Person = JxObject.defineClass(...{
name : "",
age : 0,

init : function(name, age) ...{
this.name = name;
this.age = age;
},

sayHello : function() ...{
alert("Person: name=" + this.name + ", age=" + this.age);
}
});

//从Person类继承生成Chinese类
var Chinese = JxObject.inherits(Person, ...{
addr : "",

init : function(name, age, addr) ...{
this.addr = addr;
this.__super(Person, 'init', name, age); //调用父类Person类的init方法
},
//覆写父类Person类的sayHello方法
sayHello : function() ...{
alert("你好,我叫" + this.name + ",我今年" + this.age + "岁。 "
+ "我来自" + this.addr + " "
+ "很高兴认识你!");
},

parentHello : function() ...{
alert('调用父类 sayHello()方法');
this.__super(Person, 'sayHello');
}
});

//从Person类继承生成American类
var American = JxObject.inherits(Person, ...{
//覆写父类Person类的sayHello方法
sayHello : function() ...{
alert("Hello, I'm " + this.name + ", my age is " + this.age + ". "
+ "And I'm so glad to know you!");
}
});


function hello(person) ...{
if(person instanceof Person) ...{
person.sayHello();
}else ...{
alert("Not Person object");
}
}
var xw = Chinese.getInstance('小王', 30, '湖北武汉');
var mike = American.getInstance('Mike', 20);

function test() ...{
hello(xw);
hello(mike);
hello("non");
xw.parentHello();
}
从上面的例子中,我们可以看到类的继承变得很直观了,inherits方法的第一个参数是要继承的父类,第二个参数与defineClass中的一样。通过inherits方法继承的子类,可以在子类中通过类定义的__super方法来调用父类的方法,在子类中还可以覆写父类方法。
四、总结
通过上面介绍的方法,我们现在可以比较直观地利用JavaScript来定义类了,而且我们可以在程序的任何地方来定义类及生成类的实例,如我们可以在函数内部定义类及生成类的实例:
function test(name, age) {
return JxObject.defineClass({
name : "",
age : 0,
init : function(name, age) {
this.name = name;
this.age = age;
},
sayHello : function() {
alert("Person: name=" + this.name + ", age=" + this.age);
}
}).getInstance(name, age);
}
var p = test('test', 100);
p.sayHello();
以上就是笔者对JavaScript面向对象开发的一点经验,拿出来与各位读者交流探讨。
另:笔者自己已经利用上面介绍的方法开发了一个控件库,其中包括菜单、树形控件、标签控件等,以后会发到网上来与大家共享。
本文介绍了一种在JavaScript中实现面向对象编程的新方法,包括类的定义、实例化、继承及方法覆盖等内容,使得JavaScript的面向对象编程更加直观。

被折叠的 条评论
为什么被折叠?



