Ext.extend 源码分析

来源:互联网 发布:nuance待遇 知乎 编辑:程序博客网 时间:2024/05/16 00:40
在Ext.extend中混合使用了两种继承手段:原型集成和对象冒充。

原型集成主要表现在:

                var F = function(){},                    sbp,                    spp = sp.prototype;                F.prototype = spp;                sbp = sb.prototype = new F();                //将子函数sb的构造函数指回去                sbp.constructor=sb;

对象冒充主要表现在:1、var Person = Ext.extend(Animal, {...});或者 var Person = Ext.extend(Animal, {constructor: function(){....}};情况调用下的:

sb = overrides.constructor != oc ? overrides.constructor : function(){sp.apply(this, arguments);};
2、Person = function(){

          Person.superclass.constructor.call(this, {....});

};

Ext.extend(Person, Animal, {...});


上面只是简单的对Ext.extend的实现做了简单的描述,如果不明白,请看下面对源码的详细解析,如果哪位觉得有更好的解释或者不对的地方,欢迎批评指正

        //在本方法中使用了闭包以及自执行,当浏览器加载js时就会执行该函数,然后将return的对象返回出来        extend : function(){            // inline overrides        //私有变量,对外不可调用            var io = function(o){                for(var m in o){                    this[m] = o[m];                }            };            var oc = Object.prototype.constructor;            return function(sb, sp, overrides){            /**             * 主要用做移位,例如以下两种写法:             * 1、var Person = Ext.extend(Animal, {             * name: 'huang',             *//如果子类提供了自己的构造方法,则使用自己提供的构造方法(overrides.constructor),             *//否则则使用则会赋值给一个函数:function(){sp.apply(this, arguments);             *//如果子类没有提供自己的构造方法,使用apply调用父类的构造函数,将父类中通过this赋值的属性继承下来,             *//但是父类的prototype上的属性不会被继承下来(对象冒充),对于父类静态的属性不会被继承下来             * constructor: function(){...}             * });             * 2、Ext.extend(Person, Animal, {...});             *              * 如果使用第二种方式那么if条件肯定是不成立的,也就不会给子类设置一个默认的构造函数,而是使用我们自己提供的构造函数Person进行             * 对象的构造,正因为如此,此时也享受不到Ext默认插入的这句调用:sp.apply(this, arguments);所以需要获得父类的实例属性和方法,             * 需要在构造函数中手动加入对象的冒充操作:Person.superclass.constructor.call(this, config);             */                if(Ext.isObject(sp)){                    overrides = sp;                    sp = sb;                    sb = overrides.constructor != oc ? overrides.constructor : function(){sp.apply(this, arguments);};                }                /**                 * 这里的亮点是空函数,因为空函数里面没有通过this进行赋值的属性,因此将sp.prototype 赋值给F.prototype                 * 然后将new F()赋值给sb.prototype,保证了sbp的纯净性                 */                var F = function(){},                    sbp,                    spp = sp.prototype;                F.prototype = spp;                sbp = sb.prototype = new F();                //将子函数sb的构造函数指回去                sbp.constructor=sb;                /**                 * 给子函数sb赋属性superclass,并指向sp.prototype,自定义一个属性来记录子类的父类是什么                 * 这样就可以直接调用  sb.superclass.constructor.call(this, xxx)了;                 */                sb.superclass=spp;                /**                 * 这是一个容错处理,防止父类的构造函数没有指正确,                 * 这里也是主要为了在子类中调用sb.superclass.constructor.call(this, xxx)做准备                 * 例如:Animal = function(cfg){ *this.name = "dog"; *Ext.apply(this, cfg); *} *Animal.prototype = { *eat: function(){ *alert("animal eat"); *} *} *//如果下面这一句没有写,spp.constructor 就会指向一个object *  Animal.prototype.constructor = Animal;                 */                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;                /**                 * 此处将overrides上的属性全都copy到了sb.prototype上,因此如下面的写法:                 * Animal = function(){                 * this.name = "dog";                 * }                 * Animal.prototype = {...};                 * Person = function(){                 * this.sex = "boy";                 * }                 * Ext.extends(Person, Animal, {                 * name: "kk"                 * });                 * var p = new Person();                 * p.alert(p.name);                 * 这样写也出来的结果是:dog,而不是kk,因为name:kk在prototype上,原型查找机制,对象上直接有的属性优先                 * 而如果var p = new Person({name: 'huang'});执行结果则是:huang                 */                Ext.override(sb, overrides);                sb.extend = function(o){Ext.extend(sb, o);};                return sb;            };        }(),        override : function(origclass, overrides){            if(overrides){                var p = origclass.prototype;                Ext.apply(p, overrides);                if(Ext.isIE && overrides.toString != origclass.toString){                    p.toString = overrides.toString;                }            }        },



原创粉丝点击