Ext.extend用法(ext的继承)收藏
<script type="text/javascript"><!-- function StorePage(){d=document;t=d.selection?(d.selection.type!='None'?d.selection.createRange().text:''):(d.getSelection?d.getSelection():'');void(keyit=window.open('http://www.365key.com/storeit.aspx?t='+escape(d.title)+'&u='+escape(d.location.href)+'&c='+escape(t),'keyit','scrollbars=no,width=475,height=575,left=75,top=20,status=no,resizable=yes'));keyit.focus();} // --></script>
概述
Ext.extend是Ext的继承机制,这个函数的代码相当难懂。要明白这个函数的代码,首先要知道这个函数如何使用。
使用方式
使用示例
假设有个function名为SuperClass,要实现一个子类,名为MyClass。下面的两种方式都可以实现这个功能。
- MyClass=Ext.extend(SuperClass,{/**/});
- Ext.extend(MyClass,SuperClass,{/**/});
下面来个具体示例:
- vara=function(id){
- this.id=id;
- }
- a.prototype={
- tostring:function(){
- returnthis.id;
- }
- };
- b=function(id){
- b.superclass.constructor.call(this,id);
- }
- Ext.extend(b,a,{
- tostring:function(){
- returnString.format("b:{0}",this.id);
- }
- });
- //测试一下
- varobj1=newa("obj1");
- alert(obj1.tostring());
- varobj2=newb("obj2");
- alert(obj2.tostring());
- vara=function(id){
- this.id=id;
- }
- a.prototype={
- tostring:function(){
- returnthis.id;
- }
- };
- b=Ext.extend(a,{
- tostring:function(){
- returnString.format("b:{0}",this.id);
- }
- });
- //测试一下
- varobj1=newa("obj1");
- alert(obj1.tostring());
- varobj2=newb("obj2");
- alert(obj2.tostring());
一个错误例子
下面看个示例:
- BaseClass=function(){
- this.f1=function(){
- alert("f1inbase");
- }
- this.f2=function(){
- alert("f2inbase");
- }
- }
- ChildClass=function(){
- ChildClass.superclass.constructor.call(this);
- }
- Ext.extend(ChildClass,BaseClass,{
- f1:function(){
- alert("f1inchild");
- },
- f3:function(){
- alert("f3inchild");
- }
- });
- varb=newChildClass();
- b.f1();
- b.f2();
- b.f3();
可以去执行一下,可以发现f1的执行结果仍然是"f1 in base"。并没有真正的达到override的效果。
- Ext.extendputsthepropertiesspecifiedinthe3rdargumentintothesubclass'sprototype
也就是说:第三个参数里面的函数被放置在了子类的prototype中。
而在ChildClass.superclass.constructor.call(this);这句上,BaseClass的f1成了ChildClass的变量,而不是ChildClass.prototype。通过对JavaScript的原型继承的了解,可以知道,实例变量的优先级是高于prototype的,所以上面的这个代码是达不到override的功能的。
修改的方式如下:
- BaseClass=function(){
- };
- BaseClass.prototype={
- f1:function(){
- alert("f1inbase");
- }
- };
代码解读
JavaScript中的继承实现
先了解一下最简单的继承是如何实现的:
- functionExtend(subFn,superFn){
- subFn.prototype=newsuperFn()
- subFn.prototype.constructor=subFn
- }
- functionAnimal(){
- this.say1=function(){
- alert("Animal");
- }
- }
- functionTiger(){
- this.say2=function(){
- alert("Tiger");
- }
- }
- Extend(Tiger,Animal);
- vartiger=newTiger();
- tiger.say1();//"Animal"
- tiger.say2();//"Tiger"
以看到最简单的继承只做了两件事情,一是把subFn的prototype设置为superFn的一个实例,然后设置subFn.prototype.constructor为subFn。
Ext.extend的代码
Ext.extend函数中用到了Ext.override,这个函数把第二个参数中的所有对象复制到第一个对象的prototype中。首先贴上Ext.override函数的代码:
- Ext.override=function(origclass,overrides){
- if(overrides){
- varp=origclass.prototype;
- for(varmethodinoverrides){
- p[method]=overrides[method];
- }
- }
- }
然后贴上Ext.extend的代码:
- /**
- *继承,并由传递的值决定是否覆盖原对象的属性
- *返回的对象中也增加了override()函数,用于覆盖实例的成员
- *@param{Object}subclass子类,用于继承(该类继承了父类所有属性,并最终返回该对象)
- *@param{Object}superclass父类,被继承
- *@param{Object}overrides(该参数可选)一个对象,将它本身携带的属性对子类进行覆盖
- *@methodextend
- */
- functionextend(){
- //inlineoverrides
- vario=function(o){
- for(varmino){
- this[m]=o[m];
- }
- };
- returnfunction(sb,sp,overrides){
- if(typeofsp=='object'){
- overrides=sp;
- sp=sb;
- sb=function(){sp.apply(this,arguments);};
- }
- varF=function(){},sbp,spp=sp.prototype;
- F.prototype=spp;
- sbp=sb.prototype=newF();
- sbp.constructor=sb;
- sb.superclass=spp;
- if(spp.constructor==Object.prototype.constructor){
- spp.constructor=sp;
- }
- sb.override=function(o){
- Ext.override(sb,o);
- };
- sbp.override=io;
- Ext.override(sb,overrides);
- returnsb;
- };
- }();
代码中进行了太多的简写,看起来不是特别方便,把代码中的简写补全,代码如下:
- functionextend(){
- //inlineoverrides
- varinlineOverride=function(o){
- for(varmino){
- this[m]=o[m];
- }
- };
- returnfunction(subFn,superFn,overrides){
- if(typeofsuperFn=='object'){
- //如果subFn也是对象的话(一般来说subFn这里放的是父类的构造函数),那么第三个参数overrides参数相当于被忽略掉
- overrides=superFn;
- superFn=subFn;
- //subFn重新定义了函数
- subFn=function(){
- superFn.apply(this,arguments);
- };
- }
- varF=function(){
- },subFnPrototype,superFnPrototype=superFn.prototype;
- F.prototype=superFnPrototype;
- subFnPrototype=subFn.prototype=newF();
- subFnPrototype.constructor=subFn;
- subFn.superclass=superFnPrototype;
- if(superFnPrototype.constructor==Object.prototype.constructor){
- superFnPrototype.constructor=superFn;
- }
- subFn.override=function(obj){
- Ext.override(subFn,obj);
- };
- subFnPrototype.override=inlineOverride;
- Ext.override(subFn,overrides);
- returnsubFn;
- };
- };
补全以后也不是特别容易明白,那么我们就把这个代码分开,分为2个参数和3个参数。
两个参数的Ext.extend代码
首先把代码改写成两个参数的。
- //两个参数的时候的代码,注意第二个参数必须为object
- functionextend(){
- //inlineoverrides
- varinlineOverride=function(o){
- for(varmino){
- this[m]=o[m];
- }
- };
- returnfunction(superFn,overrides){
- varsubFn=function(){
- superFn.apply(this,arguments);
- };
- varF=function(){
- },subFnPrototype,superFnPrototype=superFn.prototype;
- F.prototype=superFnPrototype;
- //注意下面两句就是上面最简单的继承实现。
- subFnPrototype=subFn.prototype=newF();
- subFnPrototype.constructor=subFn;
- //添加了superclass属性指向superFn的Prototype
- subFn.superclass=superFnPrototype;
- //为subFn和subFnPrototype添加override函数
- subFn.override=function(obj){
- Ext.override(subFn,obj);
- };
- subFnPrototype.override=inlineOverride;
- //覆盖掉子类prototype中的属性
- Ext.override(subFn,overrides);
- returnsubFn;
- };
- };
从注释中可以看到,做的工作很简单,只是定义一个subFn函数,这个函数中会调用superFn函数。定义了subFn以后,就使用上面的最简单的继承方式实现继承。然后为subFn和subFn的prototype添加了一个override函数。最后的Ext.override(subFn, overrides);把overrides中的函数写入subFn的prototype中。
三个参数的Ext.extend代码
下面我们把函数改写为只处理3个参数的,改写后的代码如下:
- //三个参数时的代码
- functionextend(){
- //inlineoverrides
- varinlineOverride=function(o){
- for(varmino){
- this[m]=o[m];
- }
- };
- returnfunction(subFn,superFn,overrides){
- varF=function(){
- },subFnPrototype,superFnPrototype=superFn.prototype;
- F.prototype=superFnPrototype;
- //注意下面两句就是上面最简单的继承实现。
- subFnPrototype=subFn.prototype=newF();
- subFnPrototype.constructor=subFn;
- //添加了superclass属性指向superFn的Prototype
- subFn.superclass=superFnPrototype;
- //为subFn和subFnPrototype添加override函数
- subFn.override=function(obj){
- Ext.override(subFn,obj);
- };
- subFnPrototype.override=inlineOverride;
- //覆盖掉子类prototype中的属性
- Ext.override(subFn,overrides);
- returnsubFn;
- };
- };
过程与两个参数的时候相差无几,只是两个参数的时候,subFn时重新定义的一个function,而三个参数的时候,这个步骤就省略了。
总结及说明
这样大家就对这个函数很明白了吧,也可以知道Ext.extend的继承只会覆写构造函数prototype中的对象,使用的时候需要多加注意。
注意下面一段代码
- if(superFnPrototype.constructor==Object.prototype.constructor){
- superFnPrototype.constructor=superFn;
- }
这段代码我在改写的Ext.extend中省略掉了。原因在于我尝试了多次,发现参数为两个参数的时候,只有第一个参数为Object对象或者为3个参数的时候,第二个参数为Object才会进入此段代码。
但是发现superFn也时function Object(){},在IE和FF下都是如此。那么我就不是很清楚这段代码到底是什么用的了,若有清楚的,告诉一声,哈。