Ext.extend方法

 extend (Object subclass,Object superclass,[Object overrides] : Object
第一个参数:子类
第二个参数:父类
第三个参数:要覆盖的属性。
这里需要强调一下,子类继承下来的是父类中通过superclass.prototype方式定义的属性(包括用此方法定义的函数)。

 

使用方式

使用示例

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

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

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

 

下面来个具体示例:

var a = function ( id ){

    this . id = id ;

}

a . prototype = {

    tostring : function (){

        return this . id ;

    }

};

           

b = function ( id ){

    b . superclass . constructor . call ( this , id );

}

Ext . extend ( b , a , {

    tostring : function (){

        return String . format ( "b:{0}" , this . id );

    }

});

// 测试一下

var obj1 = new a ( "obj1" );

alert ( obj1 . tostring ());

var obj2 = new b ( "obj2" );

alert ( obj2 . tostring ());

或者下面的代码,可以得到同样的效果:

var a = function ( id ){

    this . id = id ;

}

a . prototype = {

    tostring : function (){

       return this . id ;

    }

};

 

b = Ext . extend ( a , {

    tostring : function (){

       return String . format ( "b:{0}" , this . id );

    }

});

// 测试一下

var obj1 = new a ( "obj1" );

alert ( obj1 . tostring ());

var obj2 = new b ( "obj2" );

alert ( obj2 . tostring ());

 

一个错误例子

下面看个示例:

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 ();

 

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

 

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

 

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

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

 

修改的方式如下:

BaseClass = function () {

};

 

BaseClass . prototype = {

    f1 : function () {

        alert ( "f1 in base" );

    }

};

 

代码解读

JavaScript 中的继承实现

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

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();// "Animal"

tiger.say2();// "Tiger"

 

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

 

Ext.extend 的代码

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

Ext . override = function ( origclass , overrides ){

    if ( overrides ){

       var p = origclass . prototype ;

       for ( var method in overrides ){

           p [ method ] = overrides [ method ];

       }

    }

}

 

然后贴上 Ext.extend 的代码:

 

/**

  * 继承,并由传递的值决定是否覆盖原对象的属性

  * 返回的对象中也增加了 override() 函数,用于覆盖实例的成员

  * @param { Object } subclass 子类,用于继承(该类继承了父类所有属性,并最终返回该对象)

  * @param { Object } superclass 父类,被继承

  * @param { Object } overrides (该参数可选) 一个对象,将它本身携带的属性对子类进行覆盖

  * @method extend

  */

function extend (){

    // inline overrides

    var io = function ( o ){

       for ( var m in o ){

           this [ m ] = o [ m ];

       }

    };

    return function ( sb , sp , overrides ){

       if ( typeof sp == 'object' ){

           overrides = sp ;

           sp = sb ;

           sb = 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 == Object . prototype . constructor ){

           spp . constructor = sp ;

       }

       sb . override = function ( o ){

           Ext . override ( sb , o );

       };

       sbp . override = io ;

       Ext . override ( sb , overrides );

       return sb ;

    };

}();

 

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

function extend (){

    // inline overrides

    var inlineOverride = function ( o ){

        for ( var m in o ) {

            this [ m ] = o [ m ];

        }

    };

    return function ( subFn , superFn , overrides ){

        if ( typeof superFn == 'object' ) {

           // 如果 subFn 也是对象的话(一般来说 subFn 这里放的是父类的构造函数),那么第三个参数 overrides 参数相当于被忽略掉

            overrides = superFn ;

            superFn = subFn ;

           //subFn 重新定义了函数

            subFn = 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 == Object . prototype . constructor ) {

            superFnPrototype . constructor = superFn ;

        }

        subFn . override = function ( obj ){

            Ext . override ( subFn , obj );

        };

        subFnPrototype . override = inlineOverride ;

        Ext . override ( subFn , overrides );

        return subFn ;

    };

};

 

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

 

两个参数的 Ext.extend 代码

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

// 两个参数的时候的代码,注意第二个参数必须为 object

function extend (){

    // inline overrides

    var inlineOverride = function ( o ){

        for ( var m in o ) {

            this [ m ] = o [ m ];

        }

    };

    return function ( superFn , overrides ){

       var subFn = function (){

           superFn . apply ( this , arguments );

       };

 

        var F = function (){

        }, subFnPrototype , superFnPrototype = superFn . prototype ;

      

        F . prototype = superFnPrototype ;

       // 注意下面两句就是上面最简单的继承实现。

        subFnPrototype = subFn . prototype = new F ();

       subFnPrototype . constructor = subFn ;

       // 添加了 superclass 属性指向 superFn Prototype

       subFn . superclass = superFnPrototype ;

      

       // subFn subFnPrototype 添加 override 函数

        subFn . override = function ( obj ){

            Ext . override ( subFn , obj );

        };

        subFnPrototype . override = inlineOverride ;

       

       // 覆盖掉子类 prototype 中的属性

        Ext . override ( subFn , overrides );

        return subFn ;

    };

};

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

 

三个参数的 Ext.extend 代码

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

// 三个参数时的代码

function extend (){

    // inline overrides

    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 ;

       // 添加了 superclass 属性指向 superFn Prototype

       subFn . superclass = superFnPrototype ;

 

       // subFn subFnPrototype 添加 override 函数

        subFn . override = function ( obj ){

            Ext . override ( subFn , obj );

        };

        subFnPrototype . override = inlineOverride ;

       

       // 覆盖掉子类 prototype 中的属性

        Ext . override ( subFn , overrides );

        return subFn ;

    };

};

 

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

总结及说明

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

 

注意下面一段代码:

if ( superFnPrototype . constructor == Object . prototype . constructor ) {

    superFnPrototype . constructor = superFn ;

}

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

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

 

上面的有几段代码源自网络,若有版权侵犯,非常抱歉。

评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值