浏览 2996 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
|
|
---|---|
作者 | 正文 |
发表时间:2009-04-02
最后修改:2009-05-20
转自:http://www.bgscript.com - 背光脚本
类的继承特性可以有效的重用源代码,提高开发效率.
少JS文本体积,加快下载速度.
> Ext库:
在类声明时为 Ext.CurrentClass = Ext.extend(Ext.SuperClass, { ... });
在设计类中调用父类初始化方法为
Ext.CurrentClass.superclass.initComponent.call(this);
> jQuery:
在类声明时为 $.widget("ui.currentclass",{ ... });
在设计类中调用父类初始化方法更为显式 $.widget.prototype. initComponent.apply(this, arguments);
以上实现方式或多或少有些冗长, 根据笔者经验,有一种更好的方法,
例如 :
var MyClass = CC.create(SuperClass, function(superclass){ return { initComponent : function(options) { superclass.initComponent.call(this, options); // other codes... } }; });
这种方式有它的优点: 构建够直观,简洁. 它是将整个类包装在一起的,浑然一体,像Java类一样, 父子关系明了. 父类访问方便, 快速. 该方法把父类作为参数superclass传进来构建,子类方法通过JS闭包特性直接引用, 快速高效.子类方法中完全不必知道父类是谁. 类可以共享一些其它类没有的东西, 如变量, 方法等, 这有点像Java中类的static成员.
实现方法如下 做些前奏准备,写一个99.99%的JS库都会有的方法
// //对象属性复制方法,很多库都有实现,如PrototypeJS里面的extend和Ext里面的Ext.apply // function extend(des, src) { if (!des) des = {}; if (src) { for (var i in src) { des[i] = src[i]; } } return des; }
再定个对象,名称任意,主要是挂个方法而已,这里简单起见写为CC.
var CC = {};
以下是实现主要函数,主要是组装返回要的对象.
// //create 用于创建类 // CC.create = function(superclass, constructor){ var clazz = (function() { this.initialize.apply(this, arguments); }); //如果无参数,直接返回类. if(arguments.length == 0) return clazz; //如果无父类,此时constructor应该为一个纯对象,直接复制属性返回. if(!superclass){ extend(clazz.prototype, constructor); return clazz; } var absObj = clazz.prototype, sprPropty = superclass.prototype; if(sprPropty){ //用于访问父类方法 clazz.superclass = sprPropty; extend(absObj, sprPropty); //调用属性构造函数创建属性,这个是实现关键. extend(absObj, constructor(sprPropty)); // 子类实例直接通过obj.superclass访问父类属性, // 如果不想造成过多引用,也可把这句注释掉,因为多数时候是没必要的. absObj.superclass = sprPropty; // clazz.constructor = constructor; } return clazz; }
OK, 大功告成,写个类承继例子测试一下.
// //创建一个动物类 // var Animal = CC.create(null, { //属性 footprint : '- - - - - - =', //类初始化方法,必须的,当用 new 生成一个类时该方法自动被调用,参见上定义. initialize : function(options){ extend(this, options); alert('Animal initialize method is called.'); }, eat : function(){ alert('Animal eat method is called.'); }, move : function(){ alert('I am moving like this '+ this.footprint +' .'); } }); // //创建一个Duke类 // var Duke = CC.create(Animal, function(superclass){ //在这可以定义一些类全局静态数据,该类每个实例都共享这些数据. //计算实例个类,包括派生类实例. var static_instance_counter = 0; function classUtilityFuncHere(){ } //返回类具体属性. return { //重写初始化方法 //@override initialize : function(options) { alert('Initializing Duke class..'); //调用父类初始化,这种方法比一般其它库的要简洁点吧,可以不管父类是什么. superclass.initialize.call(this, options); //做一些子类喜欢做的事. alert('Duke initialize method is called.'); //读取或修改类静态属性 static_instance_counter++; }, //重写move方法,增加Duke自己的移动方式. move : function(){ this.footprint = this.footprint + 'zzzzzzzz'; superclass.move.call(this); }, //重写eat方法,注意,里面不调用父类方法,即父类eat被覆盖了. eat : function(){ alert('Duke is eating..'); }, //新增一个say方法,显示当前已经初始化的Duke类实例数量. say : function(){ alert('the number of Duke instances is '+static_instance_counter); } }; }); var DukeChild = CC.create(Duke, function(superclass){ return { move : function(){ this.footprint = this.footprint + '++++++++++++='; superclass.move.call(this); }, say : function(){ alert(this.msg || ''); } }; });
看看效果如何
(function test() { var animal = new Animal(); animal.eat(); animal.move(); var dukeA = new Duke(); dukeA.eat(); dukeA.move(); dukeA.say(); var dukeB = new Duke(); dukeB.eat(); dukeB.move(); dukeB.say(); var dukeC = new DukeChild({msg : 'I am a child of duke.'}); dukeC.move(); dukeC.say(); })();
这是个人的一点经验之谈,望能抛砖引玉.
声明:ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
推荐链接
|
|
返回顶楼 | |