论坛首页 Web前端技术论坛

【Extjs学习一】Extjs2继承函数简单分析及疑问

浏览 8697 次
精华帖 (0) :: 良好帖 (1) :: 新手帖 (0) :: 隐藏帖 (0)
作者 正文
   发表时间:2008-05-21  
Ext = {version: '2.0'};

 

        /**
         * 继承,并由传递的值决定是否覆盖原对象的属性
         * 返回的对象中也增加了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对象,实现原型链继承,主要要将子类的原型设置为父类的一个实例(这样子类就用有了父类原型的所有成员),并重新将子类原型的构造器设置为子类自己。
如以下代码所示:

 

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

 


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

 

function Animal(){}
function Tiger(){}
Tiger.prototype =Animal.prototype//因为@1
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

    第一种:

    /* // 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
}







































    第二种:

// 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 

 

答:的确没有

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;
};

 有

typeof c == 'object'

  这个限制,

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

        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的 所以只能这里写一个了。

        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的方式会逐级向更上层的父类调用,直到最顶端。
见:http://bbs.51js.com/viewthread.php?tid=72688&page=1&extra=#pid556697

 

 

八、相关链接

http://zhuaxia.com/pre_channel/4873283

http://bbs.51js.com/viewthread.php?tid=72688&page=1&extra=#pid556697

http://www.kevlindev.com/tutorials/javascript/inheritance/index.htm

http://www.google.cn/search?complete=1&hl=zh-CN&newwindow=1&rlz=1T4GGLS_zh-CNCN276CN276&q=Ext.extend&meta=&aq=f

http://hi.baidu.com/pmzcn/blog/item/92a05fafbe8187f8faed5057.html

 

 

 

 

 

   发表时间:2008-06-10  
我刚发的,有研究的朋友请指点指点
0 请登录后投票
   发表时间:2008-06-11  
spp.constructor == Object.prototype.constructor

这个我也不明白,似乎是为解决继承链不能超过两次?
见:
引用
I've found that its easy to build a JS OOP idiom to support one level of inheritance that fails with two more more levels of inheritiance.

http://kevlindev.com/tutorials/javascript/inheritance/index.htm

http://sp42.iteye.com/admin/blogs/201143

望引证。
0 请登录后投票
   发表时间:2008-06-11  
sp42 写道
spp.constructor == Object.prototype.constructor

这个我也不明白,似乎是为解决继承链不能超过两次?
见:
引用
I've found that its easy to build a JS OOP idiom to support one level of inheritance that fails with two more more levels of inheritiance.

http://kevlindev.com/tutorials/javascript/inheritance/index.htm

http://sp42.iteye.com/admin/blogs/201143

望引证。



我去看了 不是这个原因 不能超过两次 是通过指定subclass的superclass 和 construtor来实现的
0 请登录后投票
   发表时间:2008-06-11  
引用

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


这个的解释不对吧
真正目的是 为了获得在“构造函数里”通过 this.XXX 方式定义的属性吧
0 请登录后投票
   发表时间:2008-06-11  
fins 写道
引用

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


这个的解释不对吧
真正目的是 为了获得在“构造函数里”通过 this.XXX 方式定义的属性吧


用new F() 也是得不到的 ,所以需要显式调用 superclass.constructor.call ,
空函数就是为了避免得到superclass 构造函数 中定义 的 this.xxx 这种属性啊 ,如果需要则superclass.constructor.call要使用到了.

这个问题的提出也是围绕ext.extend的解决方案的。
0 请登录后投票
   发表时间:2008-06-11  
我说的是第一个问题 不是第二个空函数F的问题
0 请登录后投票
   发表时间:2008-06-11  
空函数是经典的闭包应用,用来解决继承的问题了 呵呵,

至于 "spp.constructor == Object.prototype.constructor",
突然想起ext的OO最近支持constructor关键字的重写了:

DeepCMS.client.layout.Menu = obj.extend(UI.TabPanel, {
	//@override
	constructor : function(){
		var config  =  {
            tabPosition     : 'bottom'
            ,title          : 'DeepCMS'
            ,region         : 'west'
            ,deferredRender : false
            ,border         : false
            ,collapsible    : true
            ,activeTab      : 1
            ,width          : 155
            ,items: [
	             new OA.client.defaultPage.sessionProfile({title: '个人信息'})
	            ,new OA.client.bigButtonArea()
            ]
        };
		DeepCMS.client.layout.Menu.superclass.constructor.call(this, config);
	}
});

注: obj = UI = Ext;
不知会不会跟这个有关系呢?呵呵
0 请登录后投票
   发表时间:2008-06-16  
我搞错了,可以支持inline constructor的原因是:
sb = [b]overrides.constructor != oc ? overrides.constructor[/b] : function(){sp.apply(this, arguments);};//第十四行

  • extend.zip (895 Bytes)
  • 描述: 附新、旧版本的extend对比
  • 下载次数: 29
0 请登录后投票
   发表时间:2008-06-17  
fins 写道
我说的是第一个问题 不是第二个空函数F的问题

我说了啊, 这些问题的提出都是围绕“ ext的继承为什么要这么写”
构造函数的this.xx在ext的继承方案中就是要避免的。
我不可能说第一个问题是为了“得到”, 第二个问题用空函数是为了“避免得到”
这样来分析吧。
所以第一个问题的着眼点是这种方式带来的副作用是“prototype联动问题”,
而采用new animal() 是可以得到this.xxx,但是这在ext的解决方案里本身是要解决的问题,而不是要达到的效果。
之所以这样分析是用了孤立的方法来各个击破各个可疑之点,从而达到能够全面分析理解各种组合情况的效果
没疑问了吧?
0 请登录后投票
论坛首页 Web前端技术版

跳转论坛:
Global site tag (gtag.js) - Google Analytics