Ext源码分析源码分析之Ext的继承模式解说——第三节、分析Ext.extend

标签:, , , , ,

这一节我们贴出Ext.extend的源代码来分析

  1. extend : function(){
  2.             // 内联函数,不懂?就是将这个方法编译后放入内存中
  3.             var io = function(o){
  4.                 for(var m in o){
  5.                     this[m] = o[m];
  6.                 }
  7.             };
  8.             return function(sb, sp, overrides){
  9.                 if(typeof sp == 'object'){//如果子类还不存在,只有父类和一些属性,那么就调用这2个参数,来构造一个子类,这里面的第三步非常神奇,很难解释的清楚,大致意思就是构造出这么匿名类,并将父类的构造方法借给它用用,嘿嘿,这么解释还不明白就留言吧
  10.                     overrides = sp;
  11.                     sp = sb;
  12.                     sb = function(){sp.apply(this, arguments);};
  13.                 }
  14.                 var F = function(){}, sbp, spp = sp.prototype;//sb代表子类,sbp代表子类prototype,sp代表父类,spp代表父类prototype
  15.                 F.prototype = spp;
  16.                 sbp = sb.prototype = new F();//其实就是child.prototype = father.prototype,new F()看不懂看第二节
  17.                 sbp.constructor=sb;//这2步一会儿细说
  18.                 sb.superclass=spp;
  19.                 if(spp.constructor == Object.prototype.constructor){//这个分支也不可以不管
  20.                     spp.constructor=sp;
  21.                 }
  22.                 sb.override = function(o){//给子类赋予一个override方法
  23.                     Ext.override(sb, o);
  24.                 };
  25.                 sbp.override = io;//给子类的对象赋予override方法
  26.                 Ext.override(sb, overrides);//将overrides里面的东西,全部赋予子类的prototype里面,不懂看第二节
  27.                 return sb;//将这个全新包装的子类返回
  28.             };
  29.         }(),

我们来详细说说 sbp.constructor=sb 这个东东,为什么要写这么一步呢?因为child.prototype = father.prototype这步执行好后,会把child的constructor给抹掉,所以要把它重新指回来,那么为什么一定要配上这个constructor呢?网上有很多解释,但大都是一抄例子了事,搞了半天还是不明白有什么用处,其实constructor只是类的一个引用,当我们把一个对象调用来调用去,我们都忘记这个对象是由谁创建的时候,它就派上用场了,obj.constructor返回的就是创建obj的那个类了,明白了吧?其次,constructor还有一个方法就是反向调用,比如这样写obj.constructor.call(this),意思是用obj去调用obj的构造方法。恩恩……非常难理解,我打算后面的章节好好介绍它的用途。

sb.superclass=spp呢?superclass又是什么?这个是Ext无中生有的一个属性而已,让子类知道它的父类是谁而已,一个标记,呵呵

综上,三部曲已经出来了吧?
第一、将属性和方法都继承下来
第二、恢复constructor,建立superclass指针
第三、将子类的属性写入到子类里

看完这3节,我想你对Ext.extend不仅有了了解,而且应该体会到Ext的编码规范,通常定义一个类,有这个三步
第一:定义Child类
Child = function(){
}
第二:Ext.extend(Child,Father,{定义Child的属性})
第三:Child.prototyp = {定义Child的方法};

或者可以只用父类和属性直接构造子类
Child = Ext.extend(Father,{});
Ext更多用这个方法,并且将方法也写入{}里面,这个方法较之上面的,多了一个神奇的第三步,见上面的代码,期间的奥秘就在于,new Child()的时候,委托谁来构造,上面是Child自己来构造,而下面这种调用方式是委托Father来构造

您照着这样的思路去看源代码定会轻松不少的:)




已经有5个留言

  1. woog Says @ 08-04-19 3:41 pm

    非常不错,学习了。

  2. Mily Says @ 08-05-3 6:55 am

    继续关注……

  3. 初学者 Says @ 08-05-28 3:05 am

    再请教二个问题:
    1. if(typeof sp == ‘object’){//这个代码块是否特指只传两个参数,与默认的三个参数正好错位,所以才导致EXT在内部处理了一下。将两个参数移位成三个参数,第三个参数就是构造出来的子类?
    2. sb.override 和sbp.override两个名字完全相同,为什么不会冲突呢?难道说属性和方法可以重名?调用的时候是怎么区分是属性还是方法呢?

  4. crab Says @ 08-05-28 2:21 pm

    1.如果只传2个参数,就把2个参数移位到后面,再创建一个function出来当sb。

    2.第一:是否重名完全取决于设计代码的规范,一般来说,方法的命名和属性的命名大不相同,几乎不会有重名发生。第二:假如真的重名,会发生覆盖,后者覆盖前者,不管是属性覆盖方法,还是方法覆盖属性。我给你段代码,你运行下,就明白了。

    var obj = {name:”xx”,name:function(){alert(”xx”)}};

    alert(obj.name);

    obj.name();

  5. thinking Says @ 08-05-31 8:05 am

    受教了!!!加深理解了!!谢谢!




留言