以下总结参考网络上资源
Ext中实现类的继承
- extend (Object subclass,Object superclass,[Object overrides] : Object)
第一个参数:子类
第二个参数:父类
第三个参数:要覆盖的属性。
这里需要强调一下,子类继承下来的是父类中通过superclass.prototype方式定义的属性(包括用此方法定义的函数),而不继承superclass中的定义的属性和方法,如果子类中的方法名与父类中相同则会覆盖。例子
父类
- BaseClass = function() {
- f1 = function() {
- alert("f1 in base");
- },
- f2 = function() {
- alert("f2 in base");
- }
- }
- BaseClass.prototype = {
- f3 : function() {
- alert("f3 in base");
- },
- f4 : function() {
- alert("f4 in base");
- }
- };
子类
- ChildClass = function() {
- }
-
- Ext.extend(ChildClass, BaseClass, {
- f1 : function() {
- alert("f1 in child");
- },
- f3 : function() {
- alert("f3 in child");
- }
- });
实例化
- var b = new ChildClass();
- b.f1();
-
- b.f3();
- b.f4();
补充:通过对 JavaScript 的原型继承的了解,可以知道,实例变量的优先级是高于 prototype 的,参见我之前写的文章javascript中静态方法、实例方法、内部方法和原型的一点见解 又如以下例子:
父类
- BaseClass = function() {
- this.f1 = function() {
- alert("f1 in base");
- },
- this.f2 = function() {
- alert("f2 in base");
- }
- }
子类
- ChildClass = function() {
- ChildClass.superclass.constructor.call( this );
- }
-
- Ext.extend(ChildClass, BaseClass, {
- f1 : function() {
- alert("f1 in child");
- },
- f3 : function() {
- alert("f3 in child");
- }
- });
实例化
- var b = new ChildClass();
- b.f1();
- b.f2();
- 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。
- function Extend(subFn, superFn) {
- subFn.prototype = new superFn();
- subFn.prototype.constructor = subFn;
- }
-
-
- function Animal() {
- this.say1 = function() {
- alert("Animal");
- }
- }
-
- function Tiger() {
- this.say2 = function() {
- alert("Tiger");
- }
-
- }
-
- Extend(Tiger, Animal);
- var tiger = new Tiger();
- tiger.say1();
- tiger.say2();
可以看到最简单的继承只做了两件事情,一是把 subFn 的 prototype 设置为 superFn 的一个实例,然后设置 subFn . prototype . constructor 为 subFn 。
Ext.extend 的代码
Ext.extend 函数中用到了 Ext.override ,这个函数把第二个参数中的所有对象复制到第一个对象的 prototype 中。首先贴上 Ext.override 函数的代码:
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- override : function(origclass, overrides){
- if(overrides){
- var p = origclass.prototype;
- Ext.apply(p, overrides);
- if(Ext.isIE && overrides.hasOwnProperty('toString')){
- p.toString = overrides.toString;
- }
- }
- }
以下是 Ext.extend的代码
-
-
-
-
-
-
-
-
- extend : function(){
-
- var io = function(o){
- for(var m in o){
- this[m] = o[m];
- }
- };
- var oc = Object.prototype.constructor;
-
-
-
- return function(sb, sp, overrides){
- if(typeof sp == 'object'){
- overrides = sp;
- sp = sb;
- sb = overrides.constructor != oc ? overrides.constructor : function(){sp.apply(this, arguments);};
- }
- var F = function(){},
- sbp,
- spp = sp.prototype;
-
- F.prototype = spp;
-
- sbp = sb.prototype = new F();
- sbp.constructor=sb;
-
- sb.superclass=spp;
- if(spp.constructor == oc){
- spp.constructor=sp;
- }
-
- sb.override = function(o){
- Ext.override(sb, o);
- };
- sbp.superclass = sbp.supr = (function(){
- return spp;
- });
- sbp.override = io;
-
- Ext.override(sb, overrides);
-
- sb.extend = function(o){return Ext.extend(sb, o);};
- return sb;
- };
- }(),
代码中进行了太多的简写,看起来不是特别方便,把代码中的简写补全,代码如下:
- extend : function(){
-
- var inlineOverride = function(o){
- for(var m in o){
- this[m] = o[m];
- }
- };
- var oc = Object.prototype.constructor;
-
- return function(subFn, superFn, overrides){
- if(typeof superFn == 'object'){
-
- overrides = superFn;
- superFn = subFn;
-
- subFn = overrides.constructor != oc ? overrides.constructor : function(){superFn.apply(this, arguments);};
- }
- var F = function(){},
- subFnPrototype,
- superFnPrototype = superFn.prototype;
-
- F.prototype = superFnPrototype;
- subFnPrototype = subFn.prototype = new F();
- subFnPrototype.constructor=subFn;
- subFn.superclass=superFnPrototype;
- if(superFnPrototype.constructor == oc){
- superFnPrototype.constructor=superFn;
- }
- subFn.override = function(o){
- Ext.override(subFn, o);
- };
- subFnPrototype.superclass = subFnPrototype.supr = (function(){
- return superFnPrototype;
- });
- subFnPrototype.override = inlineOverride;
- Ext.override(subFn, overrides);
- subFn.extend = function(o){return Ext.extend(subFn, o);};
- return subFn;
- };
- }()
代码中糅合了传两个参数和三个参数的实现,理解起来不容易明白,我们可以把代码拆分为两个参数和三个参数的实现,如下两个参数的 Ext.extend 代码
- function extend() {
-
- var inlineOverride = function(o) {
- for (var m in o) {
- this[m] = o[m];
- }
- };
- return function(superFn, overrides) {
-
- var subFn=overrides.constructor != Object.prototype.constructor ? overrides.constructor : function(){superFn.apply(this, arguments);};
-
- var F = function() {
-
- }, subFnPrototype, superFnPrototype = superFn.prototype;
-
- F.prototype = superFnPrototype;
-
-
- subFnPrototype = subFn.prototype = new F();
- subFnPrototype.constructor = subFn;
-
- if(superFnPrototype.constructor == oc){
- superFnPrototype.constructor=superFn;
- }
-
- subFn.superclass = superFnPrototype;
-
-
- subFn.override = function(obj) {
- Ext.override(subFn, obj);
- };
- subFnPrototype.override = inlineOverride;
-
-
- Ext.override(subFn, overrides);
-
- subFn.extend=function(o){
- Ext.extend(subFn,o);
- }
- return subFn;
- };
-
- };
从注释中可以看到,做的工作很简单,只是定义一个 subFn 函数,这个函数中会调用 superFn 函数。定义了 subFn 以后,就使用上面的最简单的继承方式实现继承。然后为 subFn 和 subFn 的 prototype 添加了一个 override 函数。最后的 Ext.override(subFn, overrides); 把 overrides 中的函数写入 subFn 的 prototype 中。
以下是传两个参数的简单例子
- var BaseClass = function(){};
- BaseClass.prototype = {
- method1 : function(){
- alert('father class');
- }
- };
-
- var subClass = Ext.extend(BaseClass,{
- method2 : function(){
- alert('sub class');
- }
- });
-
- var sub = new subClass();
- sub.method1();
- sub.method2();
三个参数的 Ext.extend 代码
- function extend() {
-
- var inlineOverride = function(o) {
- for (var m in o) {
- this[m] = o[m];
- }
- };
- return function(subFn, superFn, overrides) {
-
- var F = function() {
-
- }, subFnPrototype, superFnPrototype = superFn.prototype;
-
- F.prototype = superFnPrototype;
-
-
- subFnPrototype = subFn.prototype = new F();
- subFnPrototype.constructor = subFn;
-
-
- subFn.superclass = superFnPrototype;
-
- if(superFnPrototype.constructor == oc){
- superFnPrototype.constructor=superFn;
- }
-
- subFn.override = function(obj) {
- Ext.override(subFn, obj);
- };
- subFnPrototype.override = inlineOverride;
-
- Ext.override(subFn, overrides);
-
- subFn.extend = function(o) {
- Ext.extend(subFn, o);
- }
- return subFn;
- };
- };
过程与两个参数的时候相差无几,只是两个参数的时候, subFn 时重新定义的一个 function ,而三个参数的时候,这个步骤就省略了。
以下是传三个参数的例子
- var BaseClass = function(){};
- BaseClass.prototype = {
- method1 : function(){
- alert('father class');
- }
- };
-
-
- var subClass = function(){}
- Ext.extend(subClass,BaseClass,{
- method2 : function(){
- alert('sub class');
- }
- });
-
- var sub = new subClass();
- sub.method1();
- sub.method2();
这样大家就对这个函数很明白了吧,也可以知道 Ext.extend 的继承只会覆写构造函数 prototype 中的对象,使用的时候需要多加注意。