javascript 通用定义类继承工具方法

个人认为,javascript脚本语言算是一种很复杂型的语言,它不像PHP那样简单,那是因为它本身的运用环境实在是多种多样,不同的浏览器环境和其语言本身的独特性质,决定了要学好javascript语言本身实在的太不容易了。兼容不同环境和开发大型JS应用,谈何容易。在这里简单的介绍一下一个工具方法,它可以简化编写javascript类继承步骤。

首先要先回顾一下一般类继承的写法。

例子:

父类是 Rectangle . 子类是 PositionRectangle

//定义类 Rectangle
function Rectangle(w,h){
       this.width = w;
       this.height = h;
}
 //定义类公有方法 area()
Rectangle.prototype.area = function(){
       return this.width * this.height;     
}
 //定义子类
function PositionRectangle(x,y,w,h){
       //调用父类的构造器
       Rectangle.call(this,w,h);
       this.x = x;
       this.y = y;
}
 
//复制父类的原型链
PositionRectangle.prototype = new Rectangle();
 
//删除冗余的属性
delete PositionRectangle.prototype.width;
delete PositionRectangle.prototype.height;
 
//重新设置原型链的constructor,指回PositionRectangle子类
PositionRectangle.prototype.constructor = PositionRectangle;
 
//子类的方法
PositionRectangle.prototype.caculateArea = function(){
       return this.x * this.y * this.width * this.height;
}


测试:

var a = new PositionRectangle(1,2,3,4);
var area = a.caculateArea();
alert(area);

由上步骤可以,在JS里面编写类继承需要不少步骤,接下来介绍的这个工具可以简化这个步骤,这个方法是出自javascript权威指南,不过我不是很确定,原书的例子在borrows那里出现了一些问题,所以加以修改和简化,得出了一下一个版本。这个方法稍微有点复杂,其具体解决问题的步骤是:

获取相关属性——》构造原型链【调用父类构造方法构造原型链——》删除父类的局部属性和方法——》复制借用方法到原型链——》复制自定义方法到原型链——》设置constructor,superclass,classname】——》复制类本身属性和方法——》返回类。

function defineClass(data){
       //     获取相关属性
       //     data.name       :      类的名称
       //     data.extend     :      父类的引用
       //     data.constructor     :      构造函数
       //     data.methods  :      类对象方法
       //     data.statics     :      类本身的属性和方法,不属于对象
       //     data.borrows  :      表示想从某个类里面借用方法,borrows就是那个类
             
       var classname = data.name;
       var superclass = data.extend || Object;
       var constructor = data.constructor || function(){};
       var methods = data.methods || {};
       var statics = data.statics || {};
       var borrows;
      
       //     获取borrows
       if(!data.borrows) borrows = [];
       else if(data.borrows instanceof Array)  borrows = data.borrows;
       else borrows = [data.borrows];
      
      
       //     <!-- 构造类的原型链开始 -->
       //     新建一个父类的对象,用来构造原型链
       constructor.prototype = new superclass();
      
       //     获取原型属性和方法,去除局部定义的方法
       for(var p in constructor.prototype){
              if(constructor.prototype.hasOwnProperty(p)) delete constructor.prototype[p]; 
       }
      
       //     将借用的类的方法全部复制到原型链中
       for(var i = 0; i < borrows.length; i++){
              var c = borrows[i];
              for(var p in c.prototype){
                     if(typeof c.prototype[p] != "function") continue;
                     constructor.prototype[p] = c.prototype[p];
              }
       }
      
       //     将方法复制到原型链中,放在末尾可以覆盖点在借用时的同名方法
       for(var p in methods) constructor.prototype[p] = methods[p];
      
       //     设置constructor 和 superclass 属性
       constructor.prototype.constructor = constructor;
       constructor.prototype.superclass = superclass;
      
       //     设置类名称
       if(classname) constructor.prototype.classname = classname;
      
       //     <!-- 构造类的原型链结束 -->
      
       //     复制属于类本身的属性
       for(var p in statics) constructor[p] = statics[p];
      
       //     返回被构造好的类
       return constructor;
}


这个方法需要一个data对象为参数,具体属性如下:

//     data.name       :      类的名称

//     data.extend     :      父类的引用

//     data.constructor     :      构造函数

//     data.methods  :      类对象方法

//     data.statics     :      类本身的属性和方法,不属于对象

//     data.borrows  :      表示想从某个类里面借用方法,borrows就是那个类

//     data.provides  :      查询是否本类提供了provides里面所有类的所有方法,如果没有,则中断构造过程,抛出异常

一个简单的例子,实现了和上面哪个例子的同一个继承:

var Person = defineClass({
       name : "Person",
       methods : {
              say : function(){
                     alert("hello!")
              }
       }
})
 
 
var Rectangle = defineClass({
       name : "Rectangle",
       constructor :
              function(w,h){
                     this.width = w;
                     this.height = h;
              },
       methods : {
              area : function(){
                     return this.width * this.height;
              }
       }
});
 
var PositionRectangle = defineClass({
       name : "PositionRectangle",
       extend : Rectangle,
       constructor :
              function(x,y,w,h){
                     this.superclass(w,h);
                     this.x = x;
                     this.y = y;
              },
       methods : {
              caculateArea : function(){
                     return this.x * this.y * this.width * this.height;   
              }
       },
       statics : {
              positionNow : "positionNow"
       },
       borrows : Person
})
 
var a = new PositionRectangle(1,2,3,4);
var area = a.caculateArea();
alert(area)
alert(PositionRectangle.positionNow);// 类方法
a.say();// 借用方法
 


对于大型的JS应用,如果用JS构造大型的富客户端应用,或者实现JS效果框架,类继承的使用绝对是核心技术。要学好JS,切勿好高骛远。

原文链接:http://zhenpengday.blog.163.com/blog/static/165988143201011501630727/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值