论坛首页 Web前端技术论坛

Ext.extend 的一点改进

浏览 1647 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (7) :: 隐藏帖 (0)
作者 正文
   发表时间:2009-08-09  

Extjs 中的模拟继承使用很多,比如 Component 是所有 extjs 组件的基类,机制就是 Ext.extend 函数 ,所有组件实例化前都要调用父类组件的实例化程序,如:


Container :

 

 // private
    initComponent : function(){
        Ext.Container.superclass.initComponent.call(this);
.....

     }

 

这个机制也可用于一般的情况,如:

 

function base(){
		
	}
	
	base.prototype.parentMethod=function(str){
		alert('父类执行:'+str);
	}
	
	var child=Ext.extend(base,{
		parentMethod:function(str){
			
			//很不方便
			child.superclass.parentMethod.apply(this,[str]);
			
			//这样不是很好么
			//this.supermethod(str);
		}
	});
	
	var c=new child();
	c.parentMethod('原来的ext.extend');

 


就像注释中所说的,在一个子类方法中要调用父类的方法,extjs的写法有点啰嗦 ,若是override的那么直接supermethod 不就可以了么。





部分借鉴了  base2 中所实现的 javascript 类模拟机制,改造了一下 Ext.extend 很容易就实现了上述简单的写法:

 

改进的 Ext.extend

 

(function(){
		
		//函数中是否包含调用父类对应函数的代码(opera 函数不能表示)
		var hasSuper= /supermethod/.test(function(){supermethod;}) ? /\bsupermethod\b/ : /.*/;  
	
		Ext.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){
                if(typeof sp == 'object'){
                    overrides = sp;
                    sp = sb;
                    sb = overrides.constructor != oc ? overrides.constructor : function(){sp.apply(this, arguments);};
                }
                var F = function(){}, sbp, spp = sp.prototype;
                F.prototype = spp;
                
                 //不直接设置 sb.prototype = new F();
                //sbp = sb.prototype = new F();
                sbp = new F();
                                
                // 手动设置
					      for (var name in overrides) {
					     	
					     	 if(!overrides.hasOwnProperty(name)) return;
					     	
					       // 父类有这个函数
					       sbp[name] = 
					       typeof overrides[name] == "function"
					       && typeof sbp[name] == "function"
					       
					       //并且 override的函数调用了父类函数
					       && hasSuper.test(overrides[name]) ?
					       
					         (function(name, fn){
					           return function() {
					           	 	
					             var tmp = this.supermethod;
					            
					             //调用时把父类的函数存在自己的context中,供子类函数调用
					             this.supermethod = spp[name];
					            
					             
					             var ret = fn.apply(this, arguments); 
					             
					             //恢复原状,只保证调用时可以就行了
					             this.supermethod = tmp;
					            
					             return ret;
					           };
					         })(name, overrides[name]) :
					         overrides[name];
					      }
                
                sb.prototype=sbp;
                
                sbp.constructor=sb;
                sb.superclass=spp;
                if(spp.constructor == oc){
                    spp.constructor=sp;
                }
                
                
                sb.override = function(o){
                    Ext.override(sb, o);
                };
                sbp.override = io;
                
                //不需要了,前面手动做了
                //Ext.override(sb, overrides);
                
                sb.extend = function(o){Ext.extend(sb, o);};
                return sb;
            };
        }();
	
	})();
 

当然这样的话,用了闭包保存了原来的函数,内存以及效率上应该不如以前了,但是对于override的函数可以很直接的使用:

 

改进后的使用

 

child=Ext.extend(base,{
		parentMethod:function(str){	
					
			this.supermethod(str);
			alert("call child");
		},
		//原来用法保留
		otherMethod:function(){
			child.superclass.parentMethod.apply(this,['test2']);
		}
	});
	
	grand=Ext.extend(child,{
		parentMethod:function(str){			
			this.supermethod(str);
			alert("call grand");
		}
	});
	
	
	var c=new grand();
	
	c.parentMethod('改进的ext.extend');
	c.otherMethod();
 

 

 

论坛首页 Web前端技术版

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