Extjs2继承函数简单分析及疑问

Java代码
Ext = {version: '2.0'}; 

Ext = {version: '2.0'};

Java代码
        /** 
         * 继承,并由传递的值决定是否覆盖原对象的属性 
         * 返回的对象中也增加了override()函数,用于覆盖实例的成员 
         * @param {Object} subclass 子类,用于继承(该类继承了父类所有属性,并最终返回该对象) 
         * @param {Object} superclass 父类,被继承 
         * @param {Object} overrides (该参数可选) 一个对象,将它本身携带的属性对子类进行覆盖 
         * @method extend 
         */ 
        extend : function(){  
            // 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;//@1  
                F.prototype = spp;//原型链继承基本原理的实现只有这三行的部分代码 其他代码都具有技巧性,都是为了达到一定的效果或者避免一些缺点。  
                sbp = sb.prototype = new F();//用空函数 可以避免子类或得父类的实例变量 即直接定义在构造函数中的变量 避免浪费,也正是这个原因,我们需要的constructor superclass要采用下面的处理。  
                sbp.constructor=sb;//@2 设置子函数的构造函数 为什么不是sb.constructor=sb呢,请了解javascript 关于constructor的知识,主意是作为类来使用的,constructor属性为类的实例提供方便,参考@1  
                sb.superclass=spp;//这里是apply sbp的superclass 这样做不仅sb的实例可以得到superclass sb本身也可以得到  
                if(spp.constructor == Object.prototype.constructor){//  
                    spp.constructor=sp;//父类sp到达继承链的顶级 如{} 等 得指定他们的spp的构造函数 方便所有继承系列中的子类能正确调用到父类的构造函数 避免调用到Object.prototype.constructor  
                }  
                sb.override = function(o){//@3  
                    Ext.override(sb, o);  
                };//给子类本身加上override方法 方便sb的重载、重写实现  
                sbp.override = io;  
 
//给sb的子类提供好override方法//@4  @3@4可对比@2并思考区别, 为什么不写成sbp.override=function(o){Ext.apply(this,o);} ?<SPAN>  
 
 
</SPAN>  
 
 
 
 
 
 
 
 
 
 
 
                Ext.override(sb, overrides);//override属性 类级别的 区别前面 只有一个参数的 是实例级别的 没啥好说的吧?  
                return sb;  
            };  
        }(), 

        /**
         * 继承,并由传递的值决定是否覆盖原对象的属性
         * 返回的对象中也增加了override()函数,用于覆盖实例的成员
         * @param {Object} subclass 子类,用于继承(该类继承了父类所有属性,并最终返回该对象)
         * @param {Object} superclass 父类,被继承
         * @param {Object} overrides (该参数可选) 一个对象,将它本身携带的属性对子类进行覆盖
         * @method extend
         */
        extend : function(){
            // 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;//@1
                F.prototype = spp;//原型链继承基本原理的实现只有这三行的部分代码 其他代码都具有技巧性,都是为了达到一定的效果或者避免一些缺点。
                sbp = sb.prototype = new F();//用空函数 可以避免子类或得父类的实例变量 即直接定义在构造函数中的变量 避免浪费,也正是这个原因,我们需要的constructor superclass要采用下面的处理。
                sbp.constructor=sb;//@2 设置子函数的构造函数 为什么不是sb.constructor=sb呢,请了解javascript 关于constructor的知识,主意是作为类来使用的,constructor属性为类的实例提供方便,参考@1
                sb.superclass=spp;//这里是apply sbp的superclass 这样做不仅sb的实例可以得到superclass sb本身也可以得到
                if(spp.constructor == Object.prototype.constructor){//
                    spp.constructor=sp;//父类sp到达继承链的顶级 如{} 等 得指定他们的spp的构造函数 方便所有继承系列中的子类能正确调用到父类的构造函数 避免调用到Object.prototype.constructor
                }
                sb.override = function(o){//@3
                    Ext.override(sb, o);
                };//给子类本身加上override方法 方便sb的重载、重写实现
                sbp.override = io;

//给sb的子类提供好override方法//@4  @3@4可对比@2并思考区别, 为什么不写成sbp.override=function(o){Ext.apply(this,o);} ?














                Ext.override(sb, overrides);//override属性 类级别的 区别前面 只有一个参数的 是实例级别的 没啥好说的吧?
                return sb;
            };
        }(),

一、关于F的用法
Js中的类是function对象,实现原型链继承,主要要将子类的原型设置为父类的一个实例(这样子类就用有了父类原型的所有成员),并重新将子类原型的构造器设置为子类自己。
如以下代码所示:



Java代码
function Animal(){}  
function Tiger(){}  
Tiger.prototype = new Animal()//@1  
Tiger.prototype.constructor = Tiger//因为@1已经使Tiger.prototype.constructor 变为Animal,需要纠正。 

function Animal(){}
function Tiger(){}
Tiger.prototype = new Animal()//@1
Tiger.prototype.constructor = Tiger//因为@1已经使Tiger.prototype.constructor 变为Animal,需要纠正。


问题(一):为什么不采用如下这种方式呢?



Java代码
function Animal(){}  
function Tiger(){}  
Tiger.prototype =Animal.prototype//因为@1 

function Animal(){}
function Tiger(){}
Tiger.prototype =Animal.prototype//因为@1Java代码
Tiger.prototype.constructor = Tiger//因为@1已经使Tiger.prototype.constructor 变为Animal,需要纠正。 

Tiger.prototype.constructor = Tiger//因为@1已经使Tiger.prototype.constructor 变为Animal,需要纠正。


原因:为了避免对sb原型对象的操作,联动影响sp的原型对象。
问题(二):那么Ext.extent为什么要使用F这个空函数呢?
原因:用空函数,可以避免子类获得父类的实例变量 即直接定义在构造函数中的变量 避免浪费。
二、sb的原型属性是否保留

当typeof sp == "function"时,sb的原型将被替换,不保留任何原型属性,sb的superclass指向sp的原型对象;
3,当typeof sp == "object"时,sb的原型属性将被保留,sb的superclass指向自己的原型对象,效果略等同于override, 区别在于指定了superclass

三、其他要点
(一)apply,applyIf主要用于typeof == "object"时的对象操作
(二)override,extend主要用于typeof == "function"时的对象原型操作
(三)一般有两种方式使用ext.extend,建议尽量使用第二种,省去了config自己操作的麻烦。Component.js

    第一种:

Java代码
<SPAN style="FONT-SIZE: medium">    /* // protected 
     * Function to be implemented by Component subclasses to be part of standard component initialization flow (it is empty by default). 
     */ 
// Traditional constructor:  
Ext.Foo = function(config){  
    // call superclass constructor:  
    Ext.Foo.superclass.constructor.call(this, config);  
 
    this.addEvents({  
        // add events  
    });  
};  
Ext.extend(Ext.Foo, Ext.Bar, {  
   // class body  
}</SPAN> 

    /* // protected
     * Function to be implemented by Component subclasses to be part of standard component initialization flow (it is empty by default).
     */
// Traditional constructor:
Ext.Foo = function(config){
// call superclass constructor:
    Ext.Foo.superclass.constructor.call(this, config);

    this.addEvents({
// add events
    });
};
Ext.extend(Ext.Foo, Ext.Bar, {
   // class body
}







































    第二种:


Java代码
<SPAN style="FONT-SIZE: medium">// initComponent replaces the constructor:  
Ext.Foo = Ext.extend(Ext.Bar, {  
    initComponent : function(){  
        // call superclass initComponent  
        Ext.Container.superclass.initComponent.call(this);  
 
        this.addEvents({  
            // add events  
        });  
    }  
}  
</SPAN> 

// initComponent replaces the constructor:
Ext.Foo = Ext.extend(Ext.Bar, {
    initComponent : function(){
// call superclass initComponent
        Ext.Container.superclass.initComponent.call(this);

        this.addEvents({
            // add events
        });
    }
}








































四、js基础知识总结:

typeof 运算符
返回一个用来表示表达式的数据类型的字符串。

typeof
[(
)expression
[]
] ;


expression 参数是需要查找类型信息的任意表达式 。



http://book.csdn.net/bookfiles/110/1001103362.shtml

ps:js设计的一个小错误,请主意。



原始类型、引用类型 :http://book.csdn.net/bookfiles/110/1001103364.shtml

这本书可以看看:http://book.csdn.net/bookfiles/110/#c1

说明
typeof 运算符把类型信息当作字符串返回。typeof 返回值有六种可能: "number," "string," "boolean," "object," "function," 和 "undefined."

typeof 语法中的圆括号是可选项。




typeof的结果只有可能是'number','string','boolean','function','object','undefined'。new 生成的对象typeof为object。
instanceof右边一定是Number,String,Boolean,Function,Object,自定义函数对象。
.constructor的结果也只可能是Number,String,Boolean,Function,Object,自定义函数对象。
且Number,String,Boolean,Function,Object,自定义函数对象,她们的.constructor都是Function,typeof 她们 == 'function'。

掌握javascript的prototype链原理及{}.prototype为null//undifined 但是请主意Object.prototype为“object” 因为typeof Object 为"function",由此可见所以可以使用new的关键字或自定义函数, 如

new Number (),new String (),new Boolean (),new Function (),new Function (),他们都是函数类型。



五、使用extjs的一点经验

(一)充分理解继承。

(二)尽量照抄例子,从简单到复杂地进行修改,直到得到你需要的界面效果。

(三)碰到问题,快速使用google codesearch等搜索引擎。

(四)尽可能少的使用ext.get 和ext.getcmp,因为你写的类可能要再某些地方复用,避免id冲突

(后续补充中...)



六、一些疑问

(一)if(spp.constructor == Object.prototype.constructor){//   不是很理解,期待有人点拨一下



答:主要是为了解决sp为object时的继承问题 如 AB = Ext.extend(sb,Object,overrides )





(二)sbp.override = io; 为什么要使用io这个函数,类色的函数不是本来就有了嘛 如Ext.apply



答:的确没有

Js代码
Ext.apply = function(o, c, defaults){  
    if(defaults){  
        // no "this" reference for friendly out of scope calls  
        Ext.apply(o, defaults);  
    }  
    if(o && c && typeof c == 'object'){  
        for(var p in c){  
            o[p] = c[p];  
        }  
    }  
    return o;  
}; 

Ext.apply = function(o, c, defaults){
    if(defaults){
        // no "this" reference for friendly out of scope calls
        Ext.apply(o, defaults);
    }
    if(o && c && typeof c == 'object'){
        for(var p in c){
            o[p] = c[p];
        }
    }
    return o;
}; 有

Js代码
typeof c == 'object' 

typeof c == 'object'  这个限制,

applyif 虽然没这个限制,但是该函数的目的是没有的属性才会增加。

Js代码
applyIf : function(o, c){  
    if(o && c){  
        for(var p in c){  
            if(typeof o[p] == "undefined"){ o[p] = c[p]; }  
        }  
    }  
    return o;  
}, 

        applyIf : function(o, c){
            if(o && c){
                for(var p in c){
                    if(typeof o[p] == "undefined"){ o[p] = c[p]; }
                }
            }
            return o;
        },

override 是针对object.prototype的 所以只能这里写一个了。

Js代码
override : function(origclass, overrides){  
    if(overrides){  
        var p = origclass.prototype;  
        for(var method in overrides){  
            p[method] = overrides[method];  
        }  
    }  
}, 

        override : function(origclass, overrides){
            if(overrides){
                var p = origclass.prototype;
                for(var method in overrides){
                    p[method] = overrides[method];
                }
            }
        },

(三)a.superclass.constructor是c而访问不到b

                sb.superclass=spp;
                if(spp.constructor == Object.prototype.constructor){
                    spp.constructor=sp;
                }
换成
  sb.superclass=sp;
岂不是更好?

答:而且ext用的是原型链继承 subclass就是通过prototype的技巧性处理来继承superclass的 这本身是一个逐级向上的递归过程
所以指定superclass指定到superclass的prototype比较合理,而且以后调用也方便 只需要subclass.superclass.method.call
如果像你那样指定的话就需要subclass.superclass.prototype.method.call  反而更复杂了 。

subclass.superclass.call(this) 的方式没有subclass.superclass.constructor.call(this)的方式直观

而且构造函数constructor我感觉也是显示调用比较好,风格比较一致,而且少点潜规则也更容易看懂吧,没必要学java的那种方式,
而且如果superclass没有构造函数的话 按照ext的方式会逐级向更上层的父类调用,直到最顶端。

你可能感兴趣的:(C++,c,C#,prototype,ext)