关于Ext.extend源码学习

extend: function() {
            var C = function(E) {   
                for (var D in E) {
                    this[D] = E[D]  
                }
            };
            var e = Object.prototype.constructor;     
            return function(J, G, I) {                
                if (Ext.isObject(G)) {
                    I = G;
                    G = J;
                    J = I.constructor != e ? I.constructor: function() {    
                        G.apply(this, arguments)                           
                    }
                }
                var E = function() {},
                H,
                D = G.prototype;             
                E.prototype = D;
                H = J.prototype = new E();    
                H.constructor = J;      
                J.superclass = D;           
                if (D.constructor == e) {    
                    D.constructor = G      
                }
                J.override = function(F) {   
                    Ext.override(J, F)
                };
                H.superclass = H.supr = (function() { 
                    return D
                });
                H.override = C;
                Ext.override(J, I);
                J.extend = function(F) {
                    return Ext.extend(J, F)
                };
                return J
            }
        } ()

一、解读


先看看整个Ext.extend方法,从整体代码来看,extend使用了闭包,js在预编译的时候extend就是

function(J, G, I) {                
                if (Ext.isObject(G)) {
                    I = G;
                    G = J;
                    J = I.constructor != e ? I.constructor: function() {    
                        G.apply(this, arguments)                           
                    }
                }
                var E = function() {},
                H,
                D = G.prototype;             
                E.prototype = D;
                H = J.prototype = new E();    
                H.constructor = J;      
                J.superclass = D;           
                if (D.constructor == e) {    
                    D.constructor = G      
                }
                J.override = function(F) {   
                    Ext.override(J, F)
                };
                H.superclass = H.supr = (function() { 
                    return D
                });
                H.override = C;
                Ext.override(J, I);
                J.extend = function(F) {
                    return Ext.extend(J, F)
                };
                return J
            }

在使用Ext自定义一个组件的时候,一般如下定义

Ext.extend(Ext.window,{});

或者是

 Ext.extend(Ext.data.Connection, Ext.util.Observable, {})

 当第二中国情况,跳过if语句,执行下边的语句,继承Ext.util.Observable.prototype上面的属性/方法,将{}里面的数据存放到 Connection.prototype上。

如果是第一种形式那么我们会执行

if (Ext.isObject(G)) {           
                    I = G;
                    G = J;
                    J = I.constructor != e ? I.constructor: function() {   
                        G.apply( this, arguments) 
                    }
                }


这一步我觉得最最关键的就是J=I.constructor这一部分,有什么用?如果我们没有自定义的constructor,那么 创建一个function(){G.apply(this,arguments)} ,这个就是继承后组件的构造函数,当用new创建对象的时候,都会调用这个方法,如果我们有自定义的constructor,那么就使用I.construtor当做继承后组件的构造方法

再说说这个function(){G.apply(this,arguments)方法,G.apply(this,arguments)会一层一层沿着继承的层次下去,直到访问到了其父构造函数(在Ext中也就是Ext.Component。),执行父构造函数里面的代码,这时父构造函数里面的this指的是,我们在外部new创建的那个对象(子),

好的,接下来,看一下

var E = function () {},
                H,
                D = G.prototype;            
                E.prototype = D;
                H = J.prototype = new E();


刚开始,对这个中间方法,E非常不明白,为什么要使用这个方法,直接 H = J.prototype = G.prototype不就可以了吗? 它想要避免什么? 后面看了js的原型才明白,如果不使用中间方法,直接G.prototype 那么只要在J.prototype上做一些属性/方法的修改,会直接影响到G.prototype的原型。通过new E()的形式,就不会出现这些问题,同样可以继承G.prototype上的属性/方法

H.constructor = J;          
J.superclass = D;


这里H.constructor = J; 什么意思? J.prototype继承的是G.prototype上的方法/属性,那么构造函数也是G上边的,所以这里我需要让J.prototype.constructor 指向J的本身。
J.superclass = D; 这里为什么要定义一个J上的静态方法? 有什么用?,用过Ext的人应该都看到过下面的用法

Ext.Window.superclass.initComponent.call(this);


这里Ext.Window.superclass指的就是D,也就是G.prototype,在G.prototype上有一个initComponent。这里有个比较有意思的地方,也如G.apply(this,arguments)一样,会一层一层的调用下去,如同递归一样,具体调用会在下面写个例子

if (D.constructor == e) { 
   D.constructor = G  //形如D是{}形式,让他的constructor = {}      
}

从代码上看D如果是{}的形式,也就是===Object.prototype.constructor,那么改成G.prototype.constructor = {} 对于{}类型的对象,他的prototype.constructor 是Fucntion Object(){},这里做这个修改应该是Ext某些地方需要,

J.override = function(F) { //定义override静态方法,通过J.override直接调用,不需要创建对象
    Ext.override(J, F)
};
H.superclass = H.supr = ( function() {//上边J.superclass属性,这里是方法 superclass === supr
  return D
});
H.override = C; //在J.prototype定义一个override可以通过new J 来调用


上边C表示的是作用域外部已经定义好的一个方法,有点像java里面类封装的味道

Ext.override(J, I); //在{}对象直接量上的内容放到J.prototype原型上面
J.extend = function(F) { //这个实现可以使用Ext.Panel.extend({})形式代替Ext.extend(Ext.Panel,{});
   return Ext.extend(J, F)
};


第二部分:实例

Ext = {version: '1.0'}
       Ext.extend = function(arg,obj) {
            var temp = function() {arg.apply( this,arguments);} ;
             var temp1 = function () {};
            temp1.prototype = arg.prototype;
            temp.prototype = new temp1(); 
            temp.prototype.constructor = temp;
            temp.superclass = arg.prototype;
             for(var key in obj) {
                   temp.prototype[key] = obj[key];
             }
            return temp;
       }
       //测试
       Ext.ftn1 = function(b) {
             alert(b.name);
             this.getName = function () {
                   alert('ftn1');
             };
             this.name = 'ftn1 by one' ;
             this.init();
       }
       Ext.ftn1.prototype.init = function() {
      
      }
       Ext.ftn1.prototype.say = function() {
             alert('my say');
       }
       Ext.ftn2 = Ext.extend(Ext.ftn1,{
             init: function() {
                   Ext.ftn2.superclass.init.call(this);
                   this.name = '这是ftn2的name' ;
             }
      } );
      Ext.ftn3 = Ext.extend(Ext.ftn2, {
             init: function() {
                   Ext.ftn3.superclass.init.call(this);      //这里superclass是extend中的arg.prototype
                   this.name = "这是ftn3的name" ;
             }
      } );
      Ext.ftn4 = Ext.extend(Ext.ftn3, {
             init: function() {
                   Ext.ftn4.superclass.init.call(this);   //这里使用call是为了让ftn4继承ftn3的init中的this.name属性
                   this.name = "这是ftn4的name" ;
             }
      } );
       var fn4 = new Ext.ftn4({name:'stray'} ,{ age:'111'} );
      alert(fn4.name);


这个是我写的一个例子,和Extend源码大同小异。
第一步,我们看一下Ext.ftn1,按照java的角度理解,这个是一个基类,我需要从这个基类去扩展ftn2

Ext.ftn2 = Ext.extend(Ext.ftn1,{
             init: function() {
                   Ext.ftn2.superclass.init.call(this);
                   this.name = '这是ftn2的name' ;
             }
      } );

通过第一步的分析,我们知道在Extend 创建了一个function

function () {
       ftn1.apply( this,arguments);
}


这个就是第一部分代码中J, Ext.ftn2 引用的就是这个J.


同理

Ext.ftn3 = function() {
     ftn2.apply(this,argumets);
}
Ext.ftn4 = function() {
     ftn3.apply(this,arguments);
}


当我们执行 var  fn4 =  new  Ext.ftn4( { name: 'stray' }  , {  age: '111' }  );的时候
我们就去new function() {
     ftn3.apply(this,arguments);
}
会执行这个构造函数中的ftn3.apply(this,argumets);
而我们从apply用法知道接下来他会执行

Ext.ftn3 = function() {
     ftn2.apply(this,arguments)   //这时候这里的this就是fn4这个对象
}
ftn2.apply(this,arguments)就会调用
Ext.ftn2 = function() {
     ftn1.apply(this,arguments);
}
ftn1.apply(this,arguments)就会执行
Ext.ftn1 = function(b) {
             alert(b.name);
             this.getName = function () {
                   alert('ftn1');
             };
             this.name = 'ftn1 by one' ;
             this.init();
       }


呵呵,上边的this,表示什么?没错就是fn4这个对象,请看this.init() 这里init代表的就是

init: function() {
                   Ext.ftn4.superclass.init.call(this);   //这里使用call是为了让ftn4继承ftn3的init中的this.name属性
                   this.name = "这是ftn4的name" ;
             }


会运行这个init,里面   Ext.ftn4.superclass.init.call( this ); 这语句执行的时候,我们回去调用Ext.ftn4.superclass.init 也就是ftn3.init()

 init: function() {
                   Ext.ftn3.superclass.init.call(this);      //这里superclass是extend中的arg.prototype
                   this.name = "这是ftn3的name" ;
             }

这样会一层一层下去,直到调用到


Ext.ftn1.prototype.init =  function ()  {
      
}
为止
当执行完 Ext.ftn1.prototype.init以后,我们如递归一样一层一层返回定义this.name, 因为ftn2,ftn3,ftn4都有this.name那么ftn4中的this.name会覆盖其他的值,最终fn4.name = ' 这是ftn4的name ';
这样将 

Ext.ftn1 = function(b) {
             alert(b.name);
             this.getName = function () {
                   alert('ftn1');
             };
             this.name = 'ftn1 by one' ;
             this.init();
       }

执行完以后 一层一层返回,fn4对象就创建好了。我们可以使用继承过来的属性/方法







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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值