• 13.Ext.extend用法以及代码解读


    转自:http://www.blogjava.net/dragonshrimp/archive/2008/03/01/183060.html

    Ext.extend用法以及代码解读

    概述

    Ext.extend是Ext的继承机制,这个函数的代码相当难懂。要明白这个函数的代码,首先要知道这个函数如何使用。

    使用方式

    使用示例

    假设有个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下都是如此。那么我就不是很清楚这段代码到底是什么用的了,若有清楚的,告诉一声,哈。

  • 相关阅读:
    Eclipse 的快捷键
    using的用法
    二进制、八进制、十进制、十六进制之间的转换
    解决重置PostgreSQL 9.6密码的问题
    byte[]数组和int之间的转换
    【2021】IOS技术 UITableViewCell分割线无留白技巧
    【2021】IOS技术:属性观察器(Property Observers)倒计时实现
    【2019】问题记录一:后端获取URL参数的值内加号“+”变成空格“ ”
    【2015】对面向对象的理解
    “退格键”(Backspace)你想退到哪里?比较含退格的字符串
  • 原文地址:https://www.cnblogs.com/sharpest/p/7547065.html
Copyright © 2020-2023  润新知