当前位置: 代码迷 >> JavaScript >> ExtJs中沿袭的实现与理解―extend
  详细解决方案

ExtJs中沿袭的实现与理解―extend

热度:520   发布时间:2012-12-04 16:38:43.0
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 中的对象,使用的时候需要多加注意。

  相关解决方案