• 博客园logo
  • 会员
  • 周边
  • 众包
  • 新闻
  • 博问
  • 闪存
  • 赞助商
  • Chat2DB
    • 搜索
      所有博客
    • 搜索
      当前博客
  • 写随笔 我的博客 短消息 简洁模式
    用户头像
    我的博客 我的园子 账号设置 会员中心 简洁模式 ... 退出登录
    注册 登录

peter-pc

  • 博客园
  • 联系
  • 订阅
  • 管理

公告

View Post

Ext源代码阅读-001

基于V3.03 Ext.extend阅读注释:
代码如下:
        extend : function(){
            //内联属性复制(继承)
            var io = function(o){
                for(var m in o){
                    this[m] = o[m];
                }
            };
            var oc = Object.prototype.constructor;//javascript基对象构造函数

        //参数说明:
        //sb:父类构造函数
        //sp:子类需要扩展的属性
        //overrides:在sp类型为Object时没用
        //本函数的妙处在于闭包的应用,在闭包内的各种变量都将保留以备后用
        //以下的分析基于sp参数为自定义对象的情况
            return function(sb, sp, overrides){
                if(Ext.isObject(sp)){//子类扩展的属性以自定义对象形式传入
                    overrides = sp;//保存子类扩展
                    sp = sb;//执行后sp实际上就是父类构造函数了
            //如下代码是关键:
            //sp.apply(this, arguments)里此处arguments是new对象时的构造参数,比如new xxx('p')里的参数p
            //从下面代码可以看出子类构造函数有两种形式返回:
            //1.子类扩展自定义构造函数(overrides.constructor),这样本函数执行以后返回的就是用户自己定义的
            //构造函数
            //2.如果子类扩展没有定义构造函数,则以 function(){sp.apply(this, arguments) 返回,这里sp就是父类构造
            //函数,这样在执行(new 子类)的时候子类构造就会执行父类构造(通过sp.apply(this, arguments)
            //这样如果有一颗继承树的话,构造的执行将是:子类构造->调用父类构造->调用父父类构造....,一直到所有
            //父类构造执行完毕
                    sb = overrides.constructor != oc ? overrides.constructor : function(){sp.apply(this, arguments);};
                }
                var F = function(){},
                    sbp,
                    spp = sp.prototype;//父类的原型属性

                F.prototype = spp;
                sbp = sb.prototype = new F();//继承父类原型属性就在这里实现了
                sbp.constructor=sb;//纠正constructor指向(javascript每个函数的prototype.constructor应该都是指向自己的)
                sb.superclass=spp;
                if(spp.constructor == oc){
                    spp.constructor=sp;
                }
        //最后定义两个类方法override和extend以备方便使用
                sb.override = function(o){
                    Ext.override(sb, o);
                };
                sbp.superclass = sbp.supr = (function(){
                    return spp;//返回父类原型以便在子类中调用父类成员(比如被覆盖的成员)
                });
                sbp.override = io;
                Ext.override(sb, overrides);//把子类扩展属性复制到子类
                sb.extend = function(o){return Ext.extend(sb, o);};
                return sb;
            };
        }()  
    最后的()必不可少,如果少了,则执行Ext.extend(父类,子类属性)进行扩展时实际上没有执行函数体return function(sb, sp, overrides)内的扩展操作

    实际上Ext.extend只能达到继承原型属性的目的,如果需要继承动态属性,比如下面的示例:
var mypf=function()
{
    //该构造将被子类构造调用(通过sp.apply(this, arguments)
    this.x=100;//这里x是无法继承到子类的
}

//原型可以直接继承
mypf.prototype.show=function(){
    alert('mypf');
}

//扩展mypf
var myc=Ext.extend(
        mypf,
        {
            y:10,
            testme:function(){
                alert('haha');
            }
            //,//这里可以定义自己的构造函数
            //constructor:function(){}
        }
    );//这时myc中还没有mypf的x实例属性
    
var myci=new myc();//这里执行以后myci中就有mypf的x实例属性了,这里可以在构造时传入参数,这些参数将反映在sp.apply(this, arguments)中的arguments中,进而可以在父类构造中使用

根据上面的分析,父类构造将在子类实例化的时候被子类构造调用,所以这里的this.x是在(new 子类)的时候间接调用父类构造而实现的   

posted on 2009-11-28 14:00  peter-pc  阅读(1123)  评论(0)    收藏  举报

刷新页面返回顶部
 
博客园  ©  2004-2025
浙公网安备 33010602011771号 浙ICP备2021040463号-3