转载 Ext.extend用法(ext的继承)

来源:互联网 发布:人工智能医疗概念股 编辑:程序博客网 时间:2024/05/16 05:17
 

转载 Ext.extend用法(ext的继承)收藏

概述

Ext.extendExt的继承机制,这个函数的代码相当难懂。要明白这个函数的代码,首先要知道这个函数如何使用。

使用方式

使用示例

假设有个function名为SuperClass,要实现一个子类,名为MyClass。下面的两种方式都可以实现这个功能。


  1. MyClass = Ext.extend(SuperClass, { /* */ });
  2. Ext.extend(MyClass, SuperClass, { /* */});

下面来个具体示例:

  1. var a = function(id){
  2.     this.id = id;
  3. }
  4. a.prototype = {
  5.     tostring : function(){
  6.         return this.id;
  7.     }
  8. };
  9.            
  10. b = function(id){
  11.     b.superclass.constructor.call(this, id);
  12. }
  13. Ext.extend(b, a, {
  14.     tostring : function(){
  15.         return String.format("b:{0}"this.id);
  16.     }
  17. });
  18. //测试一下
  19. var obj1 = new a("obj1");
  20. alert(obj1.tostring());
  21. var obj2 = new b("obj2");
  22. alert(obj2.tostring());
或者下面的代码,可以得到同样的效果:

  1. var a = function(id){
  2.     this.id = id;
  3. }
  4. a.prototype = {
  5.     tostring : function(){
  6.        return this.id;
  7.     }
  8. };
  9.  
  10. b = Ext.extend(a, {
  11.     tostring : function(){
  12.        return String.format("b:{0}"this.id);
  13.     }
  14. });
  15. //测试一下
  16. var obj1 = new a("obj1");
  17. alert(obj1.tostring());
  18. var obj2 = new b("obj2");
  19. alert(obj2.tostring());

一个错误例子

下面看个示例:

  1. BaseClass = function() {
  2.     this.f1 = function() {
  3.         alert("f1 in base");
  4.     }
  5.  
  6.     this.f2 = function() {
  7.         alert("f2 in base");
  8.     }
  9. }
  10.  
  11. ChildClass = function() {
  12.   ChildClass.superclass.constructor.call(this);
  13. }      
  14.  
  15. Ext.extend(ChildClass, BaseClass, {
  16.     f1: function() {
  17.         alert("f1 in child");
  18.     },
  19.  
  20.     f3: function() {
  21.         alert("f3 in child");
  22.     }
  23. });
  24.  
  25. var b = new ChildClass();
  26. b.f1();
  27. b.f2();
  28. b.f3();

可以去执行一下,可以发现f1的执行结果仍然是"f1 in base"。并没有真正的达到override的效果。


  1. Ext.extend puts the properties specified in the 3rd argument into the subclass's prototype

 

也就是说:第三个参数里面的函数被放置在了子类的prototype中。

而在ChildClass.superclass.constructor.call(this);这句上,BaseClassf1成了ChildClass的变量,而不是ChildClass.prototype。通过对JavaScript的原型继承的了解,可以知道,实例变量的优先级是高于prototype的,所以上面的这个代码是达不到override的功能的。

 

修改的方式如下:

  1. BaseClass = function() {
  2. };
  3.  
  4. BaseClass.prototype = {
  5.     f1: function() {
  6.         alert("f1 in base");
  7.     }
  8. };

代码解读

JavaScript中的继承实现

先了解一下最简单的继承是如何实现的:

  1. function Extend(subFn, superFn){
  2.     subFn.prototype = new superFn()
  3.     subFn.prototype.constructor = subFn
  4. }
  5.  
  6. function Animal(){
  7.     this.say1 = function(){
  8.         alert("Animal");
  9.     }
  10. }
  11.  
  12. function Tiger(){
  13.     this.say2 = function(){
  14.         alert("Tiger");
  15.     }
  16. }
  17.  
  18. Extend(Tiger,Animal);
  19.  
  20. var tiger = new Tiger();
  21. tiger.say1();//"Animal"
  22. tiger.say2();//"Tiger"

 

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

 

Ext.extend的代码

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

 

  1. Ext.override = function(origclass, overrides){
  2.     if(overrides){
  3.        var p = origclass.prototype;
  4.        for(var method in overrides){
  5.            p[method] = overrides[method];
  6.        }
  7.     }
  8. }

 

然后贴上Ext.extend的代码:

  1. /**
  2.  * 继承,并由传递的值决定是否覆盖原对象的属性
  3.  * 返回的对象中也增加了override()函数,用于覆盖实例的成员
  4.  * @param {Object} subclass 子类,用于继承(该类继承了父类所有属性,并最终返回该对象)
  5.  * @param {Object} superclass 父类,被继承
  6.  * @param {Object} overrides (该参数可选) 一个对象,将它本身携带的属性对子类进行覆盖
  7.  * @method extend
  8.  */
  9. function extend (){
  10.     // inline overrides
  11.     var io = function(o){
  12.        for(var m in o){
  13.            this[m] = o[m];
  14.        }
  15.     };
  16.     return function(sb, sp, overrides){
  17.        if(typeof sp == 'object'){
  18.            overrides = sp;
  19.            sp = sb;
  20.            sb = function(){sp.apply(this, arguments);};
  21.        }
  22.        var F = function(){}, sbp, spp = sp.prototype;
  23.        F.prototype = spp;
  24.        sbp = sb.prototype = new F();
  25.        sbp.constructor=sb;
  26.        sb.superclass=spp;
  27.        if(spp.constructor == Object.prototype.constructor){
  28.            spp.constructor=sp;
  29.        }
  30.        sb.override = function(o){
  31.            Ext.override(sb, o);
  32.        };
  33.        sbp.override = io;
  34.        Ext.override(sb, overrides);
  35.        return sb;
  36.     };
  37. }();

 

 

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

  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.         if (typeof superFn == 'object') {
  10.            //如果subFn也是对象的话(一般来说subFn这里放的是父类的构造函数),那么第三个参数overrides参数相当于被忽略掉
  11.             overrides = superFn;
  12.             superFn = subFn;
  13.            //subFn重新定义了函数
  14.             subFn = function(){
  15.                 superFn.apply(this, arguments);
  16.             };
  17.         }
  18.         var F = function(){
  19.         }, subFnPrototype, superFnPrototype = superFn.prototype;
  20.         F.prototype = superFnPrototype;
  21.         subFnPrototype = subFn.prototype = new F();
  22.        subFnPrototype.constructor = subFn;
  23.        subFn.superclass = superFnPrototype;
  24.        
  25.        if (superFnPrototype.constructor == Object.prototype.constructor) {
  26.             superFnPrototype.constructor = superFn;
  27.         }
  28.         subFn.override = function(obj){
  29.             Ext.override(subFn, obj);
  30.         };
  31.         subFnPrototype.override = inlineOverride;
  32.         Ext.override(subFn, overrides);
  33.         return subFn;
  34.     };
  35. };

 

补全以后也不是特别容易明白,那么我们就把这个代码分开,分为2个参数和3个参数。

 

两个参数的Ext.extend代码

首先把代码改写成两个参数的。

  1. //两个参数的时候的代码,注意第二个参数必须为object
  2. function extend(){
  3.     // inline overrides
  4.     var inlineOverride = function(o){
  5.         for (var m in o) {
  6.             this[m] = o[m];
  7.         }
  8.     };
  9.     return function(superFn, overrides){
  10.        var subFn = function(){
  11.            superFn.apply(this, arguments);
  12.        };
  13.  
  14.         var F = function(){
  15.         }, subFnPrototype, superFnPrototype = superFn.prototype;
  16.       
  17.         F.prototype = superFnPrototype;
  18.        //注意下面两句就是上面最简单的继承实现。
  19.         subFnPrototype = subFn.prototype = new F();
  20.        subFnPrototype.constructor = subFn;
  21.        //添加了superclass属性指向superFn的Prototype
  22.        subFn.superclass = superFnPrototype;
  23.       
  24.        //为subFn和subFnPrototype添加override函数
  25.         subFn.override = function(obj){
  26.             Ext.override(subFn, obj);
  27.         };
  28.         subFnPrototype.override = inlineOverride;
  29.        
  30.        //覆盖掉子类prototype中的属性
  31.         Ext.override(subFn, overrides);
  32.         return subFn;
  33.     };
  34. };

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

 

三个参数的Ext.extend代码

下面我们把函数改写为只处理3个参数的,改写后的代码如下:

 

  1. //三个参数时的代码
  2. function extend(){
  3.     // inline overrides
  4.     var inlineOverride = function(o){
  5.         for (var m in o) {
  6.             this[m] = o[m];
  7.         }
  8.     };
  9.     return function(subFn, superFn, overrides){
  10.         var F = function(){
  11.         }, subFnPrototype, superFnPrototype = superFn.prototype;
  12.       
  13.         F.prototype = superFnPrototype;
  14.        //注意下面两句就是上面最简单的继承实现。
  15.         subFnPrototype = subFn.prototype = new F();
  16.        subFnPrototype.constructor = subFn;
  17.        //添加了superclass属性指向superFn的Prototype
  18.        subFn.superclass = superFnPrototype;
  19.  
  20.        //为subFn和subFnPrototype添加override函数
  21.         subFn.override = function(obj){
  22.             Ext.override(subFn, obj);
  23.         };
  24.         subFnPrototype.override = inlineOverride;
  25.        
  26.        //覆盖掉子类prototype中的属性
  27.         Ext.override(subFn, overrides);
  28.         return subFn;
  29.     };
  30. };

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

总结及说明

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

 

注意下面一段代码

 

  1. if (superFnPrototype.constructor == Object.prototype.constructor) {
  2.     superFnPrototype.constructor = superFn;
  3. }

 

这段代码我在改写的Ext.extend中省略掉了。原因在于我尝试了多次,发现参数为两个参数的时候,只有第一个参数为Object对象或者为3个参数的时候,第二个参数为Object才会进入此段代码。

但是发现superFn也时function Object(){},在IEFF下都是如此。那么我就不是很清楚这段代码到底是什么用的了,若有清楚的,告诉一声,哈。

 

原创粉丝点击