ExtJs中继承的实现与理解—extend

转自http://linder0209.iteye.com/blog/876386

 

Ext中实现类的继承

Js代码   收藏代码
  1. extend (Object subclass,Object superclass,[Object overrides] : Object)  

 
第一个参数:子类
第二个参数:父类
第三个参数:要覆盖的属性。
这里需要强调一下,子类继承下来的是父类中通过superclass.prototype方式定义的属性(包括用此方法定义的函数),而不继承superclass中的定义的属性和方法,如果子类中的方法名与父类中相同则会覆盖。例子

    父类

Js代码   收藏代码
  1. BaseClass =  function () {  
  2.  f1 = function () {  
  3.   alert("f1 in base" );  
  4.  },  
  5.  f2 = function () {  
  6.   alert("f2 in base" );  
  7.  }  
  8. }  
  9. BaseClass.prototype = {  
  10.  f3 : function () {  
  11.   alert("f3 in base" );  
  12.  },  
  13.  f4 : function () {  
  14.   alert("f4 in base" );  
  15.  }  
  16. };  

 
    子类

Js代码   收藏代码
  1. ChildClass =  function () {  
  2. }  
  3. // 继承   
  4. Ext.extend(ChildClass, BaseClass, {  
  5.    f1 : function () {  
  6.     alert("f1 in child" );  
  7.    },  
  8.    f3 : function () {  
  9.     alert("f3 in child" );  
  10.    }  
  11.   });  

 
    实例化

Js代码   收藏代码
  1. var  b =  new  ChildClass();  
  2. b.f1();// 调用子类中的实现   
  3. //b.f2();// 会报错,因为子类中没有该方法,并且父类中定义的f2是内部变量,作用域只有在内部可见(闭包)   
  4. b.f3();// 继承并覆盖,调用子类的中的实现   
  5. b.f4();// 继承,调用父类的中的实现   

 

     补充:通过对 JavaScript 的原型继承的了解,可以知道,实例变量的优先级是高于 prototype 的,参见我之前写的文章javascript中静态方法、实例方法、内部方法和原型的一点见解 又如以下例子:
    父类

Js代码   收藏代码
  1. BaseClass =  function () {  
  2.  this .f1 =  function () {  
  3.   alert("f1 in base" );  
  4.  },  
  5.  this .f2 =  function () {  
  6.   alert("f2 in base" );  
  7.  }  
  8. }  

 
    子类

Js代码   收藏代码
  1. ChildClass =  function () {  
  2.  ChildClass.superclass.constructor.call( this  );   
  3. }  
  4. // 继承   
  5. Ext.extend(ChildClass, BaseClass, {  
  6.    f1 : function () {  
  7.     alert("f1 in child" );  
  8.    },  
  9.    f3 : function () {  
  10.     alert("f3 in child" );  
  11.    }  
  12.   });  

 
    实例化

Js代码   收藏代码
  1. var  b =  new  ChildClass();  
  2. b.f1();// 调用父类中的实现,注意不会调用子类中的实现   
  3. b.f2();// 调用父类中的实现   
  4. b.f3();// 调用子类中的实现   

 

    分析:在 ChildClass.superclass.constructor.call(this); 这句上, BaseClass 的 f1 成了 ChildClass 的变量,而不是 ChildClass.prototype 。由于实例变量的优先级是高于 prototype 的,所以上面的这个代码是达不到 override 的功能的。


    了解了以上知识,下面讲解一下extend的实现,先看最简单的继承,实现原理,1、将子类的原型prototype设置为父类的一个实例,也就是说把父 类的实例赋值给子类的prototype(这样子类就有了父类原型的所有成员),2、重新将子类原型的构造器设置为子类自己,也就是把子类赋值给子类原型 的构造器。
    以下代码把 subFn 的 prototype 设置为 superFn 的一个实例,然后设置 subFn.prototype.constructor 为 subFn。

Js代码   收藏代码
  1. function  Extend(subFn, superFn) {  
  2.  subFn.prototype = new  superFn();  
  3.  subFn.prototype.constructor = subFn;  
  4. }  
  5.   
  6. //父类   
  7. function  Animal() {  
  8.  this .say1 =  function () {  
  9.   alert("Animal" );  
  10.  }  
  11. }  
  12. //子类   
  13. function  Tiger() {  
  14.  this .say2 =  function () {  
  15.   alert("Tiger" );  
  16.  }  
  17.   
  18. }  
  19. //继承应用   
  20. Extend(Tiger, Animal);  
  21. var  tiger =  new  Tiger();  
  22. tiger.say1();// "Animal"   
  23. tiger.say2();// "Tiger"   

 

     可以看到最简单的继承只做了两件事情,一是把 subFn 的 prototype 设置为 superFn 的一个实例,然后设置 subFn . prototype . constructor 为 subFn 。


Ext.extend 的代码


     Ext.extend 函数中用到了 Ext.override ,这个函数把第二个参数中的所有对象复制到第一个对象的 prototype 中。首先贴上 Ext.override 函数的代码:

Js代码   收藏代码
  1. /**  
  2.          * Adds a list of functions to the prototype of an existing class, overwriting any existing methods with the same name.  
  3.          * Usage:<pre><code>  
  4. Ext.override(MyClass, {  
  5.     newMethod1: function(){  
  6.         // etc.  
  7.     },  
  8.     newMethod2: function(foo){  
  9.         // etc.  
  10.     }  
  11. });  
  12. </code></pre>  
  13.          * @param {Object} origclass The class to override  
  14.          * @param {Object} overrides The list of functions to add to origClass.  This should be specified as an object literal  
  15.          * containing one or more methods.  
  16.          * @method override  
  17.          */   
  18.         override : function (origclass, overrides){  
  19.             if (overrides){  
  20.                 var  p = origclass.prototype;  
  21.                 Ext.apply(p, overrides);  
  22.                 if (Ext.isIE && overrides.hasOwnProperty( 'toString' )){  
  23.                     p.toString = overrides.toString;  
  24.                 }  
  25.             }  
  26.         }  

 

    以下是 Ext.extend的代码

Js代码   收藏代码
  1. /**   
  2.   * 继承,并由传递的值决定是否覆盖原对象的属性   
  3.   * 返回的对象中也增加了 override() 函数,用于覆盖实例的成员   
  4.   * @param { Object } subclass 子类,用于继承(该类继承了父类所有属性,并最终返回该对象)   
  5.   * @param { Object } superclass 父类,被继承   
  6.   * @param { Object } overrides (该参数可选) 一个对象,将它本身携带的属性对子类进行覆盖   
  7.   * @method extend   
  8.   */    
  9.         extend : function (){  
  10.             // inline overrides   
  11.             var  io =  function (o){  
  12.                 for ( var  m  in  o){  
  13.                     this [m] = o[m];  
  14.                 }  
  15.             };  
  16.             var  oc = Object.prototype.constructor;  
  17.   
  18.             //匿名函数实现   
  19.             //三个参数sb、sp、overrides分别代表subClass(子类)、superClass(父类)及覆盖子类的配置参数   
  20.             return   function (sb, sp, overrides){  
  21.                 if ( typeof  sp ==  'object' ){ //传递两个参数时superClass, overrides   
  22.                     overrides = sp;  
  23.                     sp = sb;  
  24.                     sb = overrides.constructor != oc ? overrides.constructor : function (){sp.apply( this , arguments);};  
  25.                 }  
  26.                 var  F =  function (){}, //定义一空函数,用来赋给其对象时清空该对象   
  27.                     sbp,  
  28.                     spp = sp.prototype;  
  29.   
  30.                 F.prototype = spp;  
  31.                 // 注意下面两句就是JavaScript中最简单的继承实现。   
  32.                 sbp = sb.prototype = new  F(); //清空   
  33.                 sbp.constructor=sb;  
  34.                 // 添加了 superclass 属性指向 superclass 的 prototype   
  35.                 sb.superclass=spp;  
  36.                 if (spp.constructor == oc){  
  37.                     spp.constructor=sp;  
  38.                 }  
  39.                 // 为 subClass 和 subClassPrototype 添加 override 函数   
  40.                 sb.override = function (o){  
  41.                     Ext.override(sb, o);  
  42.                 };  
  43.                 sbp.superclass = sbp.supr = (function (){  
  44.                     return  spp;  
  45.                 });  
  46.                 sbp.override = io;  
  47.                 // 覆盖掉子类 prototype 中的属性   
  48.                 Ext.override(sb, overrides);  
  49.                 //为子类加上类方法:extend   
  50.                 sb.extend = function (o){ return  Ext.extend(sb, o);};  
  51.                 return  sb;  
  52.             };  
  53.         }(),  

 

    代码中进行了太多的简写,看起来不是特别方便,把代码中的简写补全,代码如下:

Js代码   收藏代码
  1. extend :  function (){  
  2.             // inline overrides   
  3.             var  inlineOverride =  function (o){  
  4.                 for ( var  m  in  o){  
  5.                     this [m] = o[m];  
  6.                 }  
  7.             };  
  8.             var  oc = Object.prototype.constructor;  
  9.   
  10.             return   function (subFn, superFn, overrides){  
  11.                 if ( typeof  superFn ==  'object' ){  
  12.                  // 如果 superFn 也是对象的话(一般来说 superFn 这里放的是父类的构造函数),那么第三个参数 overrides 参数相当于被忽略掉   
  13.                     overrides = superFn;  
  14.                     superFn = subFn;  
  15.                     //重新定义了函数 subFn    
  16.                     subFn = overrides.constructor != oc ? overrides.constructor : function (){superFn.apply( this , arguments);};  
  17.                 }  
  18.                 var  F =  function (){},  
  19.                     subFnPrototype,  
  20.                     superFnPrototype = superFn.prototype;  
  21.   
  22.                 F.prototype = superFnPrototype;  
  23.                 subFnPrototype = subFn.prototype = new  F();  
  24.                 subFnPrototype.constructor=subFn;  
  25.                 subFn.superclass=superFnPrototype;  
  26.                 if (superFnPrototype.constructor == oc){  
  27.                     superFnPrototype.constructor=superFn;  
  28.                 }  
  29.                 subFn.override = function (o){  
  30.                     Ext.override(subFn, o);  
  31.                 };  
  32.                 subFnPrototype.superclass = subFnPrototype.supr = (function (){  
  33.                     return  superFnPrototype;  
  34.                 });  
  35.                 subFnPrototype.override = inlineOverride;  
  36.                 Ext.override(subFn, overrides);  
  37.                 subFn.extend = function (o){ return  Ext.extend(subFn, o);};  
  38.                 return  subFn;  
  39.             };  
  40.         }()  

 

     代码中糅合了传两个参数和三个参数的实现,理解起来不容易明白,我们可以把代码拆分为两个参数和三个参数的实现,如下两个参数的 Ext.extend 代码

 

Js代码   收藏代码
  1. function  extend() {  
  2.  // inline overrides   
  3.  var  inlineOverride =  function (o) {  
  4.   for  ( var  m  in  o) {  
  5.    this [m] = o[m];  
  6.   }  
  7.  };  
  8.  return   function (superFn, overrides) {  
  9.   // 定义返回的子类   
  10.   var  subFn=overrides.constructor != Object.prototype.constructor ? overrides.constructor :  function (){superFn.apply( this , arguments);};  
  11.   //以下为中间变量,或叫过程变量   
  12.   var  F =  function () {  
  13.   
  14.   }, subFnPrototype, superFnPrototype = superFn.prototype;  
  15.   
  16.   F.prototype = superFnPrototype;//F中含有了所有 superFn.prototype 中的功能   
  17.   
  18.   // 注意下面两句就是JavaScript中最简单的继承实现。   
  19.   subFnPrototype = subFn.prototype = new  F();  
  20.   subFnPrototype.constructor = subFn;  
  21.   //改变父类实例对象中的constructor,使其指向自身的构建函数   
  22.   if (superFnPrototype.constructor == oc){  
  23.         superFnPrototype.constructor=superFn;  
  24.   }  
  25.   // 添加了 superclass 属性指向 superFn 的 prototype   
  26.   subFn.superclass = superFnPrototype;  
  27.   
  28.   // 为 subFn 和 subFnPrototype 添加 override 函数   
  29.   subFn.override = function (obj) {  
  30.    Ext.override(subFn, obj);  
  31.   };  
  32.   subFnPrototype.override = inlineOverride;  
  33.     
  34.   // 覆盖掉子类 prototype 中的属性   
  35.   Ext.override(subFn, overrides);  
  36.   //为子类加上类方法:extend   
  37.   subFn.extend=function (o){  
  38.    Ext.extend(subFn,o);  
  39.   }  
  40.   return  subFn;  
  41.  };  
  42.   
  43. };  

 

     从注释中可以看到,做的工作很简单,只是定义一个 subFn 函数,这个函数中会调用 superFn 函数。定义了 subFn 以后,就使用上面的最简单的继承方式实现继承。然后为 subFn 和 subFn 的 prototype 添加了一个 override 函数。最后的 Ext.override(subFn, overrides); 把 overrides 中的函数写入 subFn 的 prototype 中。

     以下是传两个参数的简单例子

 

Js代码   收藏代码
  1. var  BaseClass =  function (){};  
  2. BaseClass.prototype = {  
  3.     method1 : function (){  
  4.         alert('father class' );  
  5.     }  
  6. };  
  7. //两个参数的继承   
  8. var  subClass = Ext.extend(BaseClass,{  
  9.     method2 : function (){  
  10.         alert('sub class' );  
  11.     }  
  12. });  
  13.   
  14. var  sub =  new  subClass();  
  15. sub.method1();  
  16. sub.method2();  
 

    三个参数的 Ext.extend 代码

Js代码   收藏代码
  1. function  extend() {  
  2.  // inline overrides   
  3.  var  inlineOverride =  function (o) {  
  4.   for  ( var  m  in  o) {  
  5.    this [m] = o[m];  
  6.   }  
  7.  };  
  8.  return   function (subFn, superFn, overrides) {  
  9.         // 以下为中间变量,或叫过程变量   
  10.   var  F =  function () {  
  11.   
  12.   }, subFnPrototype, superFnPrototype = superFn.prototype;  
  13.   
  14.   F.prototype = superFnPrototype;// F中含有了所有 superFn.prototype 中的功能   
  15.   
  16.   // 注意下面两句就是JavaScript中最简单的继承实现。   
  17.   subFnPrototype = subFn.prototype = new  F();  
  18.   subFnPrototype.constructor = subFn;  
  19.   
  20.   // 添加了 superclass 属性指向 superFn 的 Prototype   
  21.   subFn.superclass = superFnPrototype;  
  22.   //改变父类实例对象中的constructor,使其指向自身的构建函数   
  23.   if (superFnPrototype.constructor == oc){  
  24.         superFnPrototype.constructor=superFn;  
  25.   }   
  26.   // 为 subFn 和 subFnPrototype 添加 override 函数   
  27.   subFn.override = function (obj) {  
  28.    Ext.override(subFn, obj);  
  29.   };  
  30.   subFnPrototype.override = inlineOverride;  
  31.   // 覆盖掉子类 prototype 中的属性   
  32.   Ext.override(subFn, overrides);  
  33.   // 为子类加上类方法:extend   
  34.   subFn.extend = function (o) {  
  35.    Ext.extend(subFn, o);  
  36.   }  
  37.   return  subFn;  
  38.  };  
  39. };  

 
      过程与两个参数的时候相差无几,只是两个参数的时候, subFn 时重新定义的一个 function ,而三个参数的时候,这个步骤就省略了。

 

      以下是传三个参数的例子

Js代码   收藏代码
  1. var  BaseClass =  function (){};  
  2. BaseClass.prototype = {  
  3.     method1 : function (){  
  4.     alert('father class' );  
  5.     }  
  6. };  
  7.   
  8. //三个参数的继承   
  9. var  subClass =  function (){}  
  10. Ext.extend(subClass,BaseClass,{  
  11.    method2 : function (){  
  12.     alert('sub class' );  
  13.    }  
  14. });  
  15.   
  16. var  sub =  new  subClass();  
  17. sub.method1();  
  18. sub.method2();  
 


      这样大家就对这个函数很明白了吧,也可以知道 Ext.extend 的继承只会覆写构造函数 prototype 中的对象,使用的时候需要多加注意。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值