前面在JavaScript中继承的实现方法 讲了JavaScript中继承的几种实现方法,这段时间正好在看AJS框架,该框架中用到的是“拷贝继承法”,于是自己仿照写了一个简单的“拷贝继承法”的框架,并加了一些具体的注释,但是有的地方不知道怎样去描述,觉得有不妥的地方,待理解更加透彻之后再修改。
附上源代码:
<script language="JavaScript">
//拷贝继承法的使用
//引擎类EngineClass的作用是完成继承操作
//父类ParentClass是引擎类EngineClass的对象
//子类ChildClass是调用ParentClass.extend返回的对象。其实,ChildClass就是继承ParentClass的子类
//定义引擎类EngineClass
EngineClass = function(members)
{
var fn = function()
{
if(arguments[0] != 'no_init') //如果没有必须执行的方法,该函数体可以为空。
{
return this.NeedInit.apply(this, arguments); //初始化类中必须有NeedInit方法
//构造函数 改变this.NeedInit函数中的this指针(即函数内部的this)。执行继承该类的this.NeedInit函数
}
}
fn.prototype = members; //将参数中的方法赋给prototype,创建类对象后,就可以用对象来调用相应的方法
for(var i in EngineClass.prototype) //将EngineClass的prototype属性赋给类对象
fn[i] = EngineClass.prototype[i];
return fn;
}
EngineClass.prototype =
{
extend: function(members) //拷贝继承法 扩展members成员,然后传入到EngineClass类构造函数,返回EngineClass对象
{
var parentmembers = new this('no_init');
//调用构造函数 即EngineClass中的fn() 返回parentClass对象中方法列表对象
for(k in members) //将父类和子类的方法都合并起来,并且形成继承关系
{
var prev = parentmembers[k]; //父类的方法
var cur = members[k]; //子类的方法
if (prev && prev != cur && typeof cur == 'function')
{
cur = this.__parentize(cur, prev);
//如果父类对象中有该方法,则更改子方法中的this指针,让子类中的方法可以调用父类的同名方法
}
parentmembers[k] = cur; //将子类中的方法加入到父类对象中来(同名则覆盖)
}
return new EngineClass(parentmembers); //返回类对象(父类和子类的方法都合并起来)
},
__parentize: function(cur, prev) //指定父类同名方法
{
return function()
{
this.parent = prev; //在子类中调用this.parent({});就可以调用父类的同名方法了。
return cur.apply(this, arguments);
//this代表EngineClass对象(加了parent)这样子类中的方法就调用父类的同名方法了
}
},
init: function()
{
alert('初始化EngineClass后就可以调用我');
}
}
//创建基类EngineClass的对象ParentClass(ParentClass对象可以调用extend,init方法) ParentClass相当于基类
//将{init,func2,func3}作为参数赋给EngineClass构造函数的members
ParentClass = new EngineClass
(
{
NeedInit: function()
{
alert('ParentClass父类,该方法必须存在! 我有子类来调用');
},
ParentClassinit: function()
{
alert('1、EngineClass做拷贝继承操作 2、必须对象化ChildClass类 才能调用ParentClassinit');
}
}
)
//ChildClass将返回ParentClass.extend方法中的返回的对象,如果该方法中为空,则表示返回undefined
//所以要要求EngineClass类的extend方法要做一些拷贝方法的操作,来完成继承操作 ChildClass相当于继承ParentClass的子类
//调用extend方法,将{func1,func2,func3}作为参数赋给members
ChildClass = ParentClass.extend
(
{
NeedInit: function() //创建对象时就调用了。
{
alert('ChildClass子类,该方法必须存在!创建对象时就调用了,类似构造函数');
this.parent({});//调用父类的NeedInit方法
},
ChildClassinit: function()
{
alert('1、EngineClass做拷贝继承操作 2、必须对象化ChildClass类 才能调用ChildClassinit');
}
}
)
var current = new ChildClass();
current.ChildClassinit(); //类的prototype方法,必须初始化对象后才能调用
current.ParentClassinit(); //类的prototype方法,必须初始化对象后才能调用
ParentClass.init(); //不是类的prototype方法,不必初始化对象,可以直接调用
ChildClass.init();
</script>
//拷贝继承法的使用
//引擎类EngineClass的作用是完成继承操作
//父类ParentClass是引擎类EngineClass的对象
//子类ChildClass是调用ParentClass.extend返回的对象。其实,ChildClass就是继承ParentClass的子类
//定义引擎类EngineClass
EngineClass = function(members)
{
var fn = function()
{
if(arguments[0] != 'no_init') //如果没有必须执行的方法,该函数体可以为空。
{
return this.NeedInit.apply(this, arguments); //初始化类中必须有NeedInit方法
//构造函数 改变this.NeedInit函数中的this指针(即函数内部的this)。执行继承该类的this.NeedInit函数
}
}
fn.prototype = members; //将参数中的方法赋给prototype,创建类对象后,就可以用对象来调用相应的方法
for(var i in EngineClass.prototype) //将EngineClass的prototype属性赋给类对象
fn[i] = EngineClass.prototype[i];
return fn;
}
EngineClass.prototype =
{
extend: function(members) //拷贝继承法 扩展members成员,然后传入到EngineClass类构造函数,返回EngineClass对象
{
var parentmembers = new this('no_init');
//调用构造函数 即EngineClass中的fn() 返回parentClass对象中方法列表对象
for(k in members) //将父类和子类的方法都合并起来,并且形成继承关系
{
var prev = parentmembers[k]; //父类的方法
var cur = members[k]; //子类的方法
if (prev && prev != cur && typeof cur == 'function')
{
cur = this.__parentize(cur, prev);
//如果父类对象中有该方法,则更改子方法中的this指针,让子类中的方法可以调用父类的同名方法
}
parentmembers[k] = cur; //将子类中的方法加入到父类对象中来(同名则覆盖)
}
return new EngineClass(parentmembers); //返回类对象(父类和子类的方法都合并起来)
},
__parentize: function(cur, prev) //指定父类同名方法
{
return function()
{
this.parent = prev; //在子类中调用this.parent({});就可以调用父类的同名方法了。
return cur.apply(this, arguments);
//this代表EngineClass对象(加了parent)这样子类中的方法就调用父类的同名方法了
}
},
init: function()
{
alert('初始化EngineClass后就可以调用我');
}
}
//创建基类EngineClass的对象ParentClass(ParentClass对象可以调用extend,init方法) ParentClass相当于基类
//将{init,func2,func3}作为参数赋给EngineClass构造函数的members
ParentClass = new EngineClass
(
{
NeedInit: function()
{
alert('ParentClass父类,该方法必须存在! 我有子类来调用');
},
ParentClassinit: function()
{
alert('1、EngineClass做拷贝继承操作 2、必须对象化ChildClass类 才能调用ParentClassinit');
}
}
)
//ChildClass将返回ParentClass.extend方法中的返回的对象,如果该方法中为空,则表示返回undefined
//所以要要求EngineClass类的extend方法要做一些拷贝方法的操作,来完成继承操作 ChildClass相当于继承ParentClass的子类
//调用extend方法,将{func1,func2,func3}作为参数赋给members
ChildClass = ParentClass.extend
(
{
NeedInit: function() //创建对象时就调用了。
{
alert('ChildClass子类,该方法必须存在!创建对象时就调用了,类似构造函数');
this.parent({});//调用父类的NeedInit方法
},
ChildClassinit: function()
{
alert('1、EngineClass做拷贝继承操作 2、必须对象化ChildClass类 才能调用ChildClassinit');
}
}
)
var current = new ChildClass();
current.ChildClassinit(); //类的prototype方法,必须初始化对象后才能调用
current.ParentClassinit(); //类的prototype方法,必须初始化对象后才能调用
ParentClass.init(); //不是类的prototype方法,不必初始化对象,可以直接调用
ChildClass.init();
</script>