在此之前,刚接触JS面向对象的童鞋可先阅读一下这两个系列的文章:Javascript面向对象编程 和 JavaScript继承详解。
我也了解jQuery、Prototype这几个框架对面向对象的实现方式,就我个人比较的结果,最后发现还是ExtJS的实现最优雅,用那种方式开发出来的代码可读性更好(个人觉得)。可先参阅 ExtJS的面向对象相关文档。
如果项目足够庞大的话,可以直接把ExtJS的实现copy出来用。但是,对于一般的项目的来说,ExtJS的面向对象的东西实现得过于多了点,功能过于臃肿了点,比如我就不希望实现静态成员这个功能,不希望实现mixins等这些很少用的功能。因为静态成员无非就是一些用类名称直接调用的函数,其实从实际意义上来说完全可以写成挂到某命名空间下的函数集(类名称相当于一个命名空间),这是其一,其二是我们在开发中有多少情况需要静态成员?很少吧。所以不必实现这个功能。
所以我简单实现了一下ExtJS那种面向对象方式,下面先贴怎么使用这种方式进行面向对象程序设计的例子,然后再贴出实现代码。
<!DOCTYPE html>
<html>
<head>
<title>class test</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<script type="text/javascript" src="define.js"></script>
</head>
<body>
<div style="width:500px;margin:0 auto;">
<div style="color:#0000ff;">输出信息:</div>
<div id="log" class="result"></div>
</div>
<script type="text/javascript">
function trace(msg){
document.getElementById('log').innerHTML += msg+'<br/>';
}
try{
//* 删掉一个反斜线则恢复注释,相反,两个反斜线就是让下面这块代码可以运行
//类的定义
var People = N.define({
constructor: function(name){ //类的构造器(构造函数)
this.name = name; //类的成员
this.oneObj = {kkk: 5};
},
hometown: '北京',
testObj: {abc:1}, //这也是类的成员,请留意构造器里定义的成员和构造器外定义的成员的共享情况
getName: function(){ //类的方法
trace(this.name);
},
setHometown: function(hometown){
this.hometown = hometown;
this.testObj.abc = 2;
this.oneObj.kkk = 6;
},
getHometown: function(){
trace(this.hometown);
trace(this.testObj.abc);
trace(this.oneObj.kkk);
}
});
var lm = new People('李明');
lm.getName();
lm.setHometown('上海');
lm.getHometown();
var xh = new People('肖华');
xh.getName();
xh.getHometown();
// */
/*
//类的继承
var People = N.define({
constructor: function(name){
this.name = name;
},
getName: function(){
trace(this.name);
},
move: function(){
trace(this.name+' 动一动。。');
}
});
var Woman = N.define({
extend: People, //继承哪个父类
constructor: function(name, friend){
this.friend = friend;
},
//方法重载
getName: function(){
trace('我的名字叫'+this.name);
},
getFriend: function(){
trace('我的朋友是'+this.friend);
}
});
var xh = new Woman('李小花', 'Lily');
xh.getName();
xh.getFriend();
xh.move(); //父类方法
var hmm = new Woman('韩梅梅', '李雷');
hmm.getName();
hmm.getFriend();
// */
/*
//接口的实现
var InterfA = {getName:1}; //接口就是一个个纯对象
var InterfB = {run:1};
var Woman = N.define({
implement: [InterfA], //[InterfA, InterfB], //要实现的接口,把所有接口放到一个数组里
constructor: function(name, friend){
this.name = name;
this.friend = friend;
},
getName: function(){
trace('我的名字叫'+this.name);
},
getFriend: function(){
trace('我的朋友是'+this.friend);
}
});
var xh = new Woman('李小花', 'Lily');
xh.getName();
xh.getFriend();
// */
/*d//
//类的继承,实现接口
var People = N.define({
constructor: function(name){
this.name = name;
},
getName: function(){
trace(this.name);
},
move: function(){
trace(this.name+' 动一动。。');
}
});
var InterfA = {getName:1};
var InterfB = {run:1};
var Woman = N.define({
extend: People,
implement: [InterfA, InterfB],
constructor: function(name, friend){
this.friend = friend;
},
//方法重载
getName: function(){
trace('我的名字叫'+this.name);
//this.$super.getName();
},
run: function(){
this.$super.move(); //在子类里调用父类的方法
trace(this.name+' is running and running...');
},
getFriend: function(){
trace('我的朋友是'+this.friend);
}
});
var xh = new Woman('李小花', 'Lily');
xh.getName();
xh.getFriend();
xh.move(); //父类方法
var hmm = new Woman('韩梅梅', '李雷');
hmm.getName();
hmm.getFriend();
hmm.run();
var lm = new People('李明');
lm.getName();
//d*/
}catch(e){alert(e)}
</script>
</body>
</html>
实现这种面向对象方式的JS代码:define.js文件
/**
* @fileoverview 类的定义,继承,接口实现
*/
var N = {};
N.define = function(classInfo){
function F(){}
if( typeof classInfo !== 'object' ){
return F;
}
var constructor = classInfo.constructor || F,
superclass = classInfo.extend,
implement = classInfo.implement,
newclass,
prototype,
k;
//!!!继承父类
if( superclass ){
var superPrototype = superclass.prototype;
newclass = function(){
var _this = this;
this.$super = {};
for(k in superPrototype){
if( typeof superPrototype[k] === 'function' ){
this.$super[k] = (function(fn){
return function(){
return fn.apply(_this, arguments);
}
})(superPrototype[k]);
}
}
superclass.apply(this, arguments);
constructor.apply(this, arguments);
};
F.prototype = superPrototype;
newclass.prototype = new F();
//newclass.prototype.constructor = newclass;
delete classInfo.extend;
}else{
newclass = constructor;
}
prototype = newclass.prototype;
delete classInfo.constructor;
delete classInfo.implement;
//!!!添加公共成员(方法、属性),不支持私有成员或保护成员
for(k in classInfo){
if(classInfo.hasOwnProperty(k)) {
prototype[k] = classInfo[k];
}
}
//设置原型链的constructor
prototype.constructor = newclass;
//!!!实现接口的话,检查是否实现所有接口方法
if( implement ){
for(var i=implement.length, interf; i--;){
interf = implement[i];
if(typeof interf !== 'object'){
//implement语句错误:参数必须为object类型
throw 'An interface must be object type!';
}
for(k in interf){
if( typeof prototype[k]!=='function' && interf.hasOwnProperty(k) ){
throw 'NOT implement the function [' + k + ']!';
}
}
}
}
return newclass;
};
接口继承的话,直接用对象的浅拷贝就能实现接口继承。
请各位童鞋提改进意见。