个人认为,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/