日期:2014-05-16  浏览次数:20440 次

手工打造Extjs (1) 类系统



最近看了几本javascrpt方面的书(javascript高级程序设计,javascript设计模式),内容中讲到很多面向对象式开发也提到很多优秀的javascript框架,
我很是费解为什么就没有提到过Extjs,难道YUI跟Extjs有那么大得深仇大恨?。


转入正题,我特别喜欢Extjs4 的类体系,所以就自己模仿的写了一个,我只是简单了解过extjs并没有深入去学习,所以有些地方可能不对还望大家指出。


在我的类体系中可以声明接口、抽象类、类,声明方式与extjs类似


下面是Extjs的类声明
Ext.define('Ext.panel.Panel', {
extend: 'Ext.panel.AbstractPanel'
// .....
})

下面是代码 :ClassManager.js


var Design = Design || {};


(function(Class) {
	/*先定义一些工具方法*/
	
	var widgetMap = {};
	
	var util = {
		/* 复制对象的属性,如果他们不存在 */
		applyIf: function(c1, c2) {
			if(typeof c1 == "object" && typeof c2 == "object"){
				for(var key in c2) {
					if(!c1[key]){
						c1[key] = c2[key];
					}
				}
			}
		},
		/* 复制对象的属性*/
		apply: function(c1, c2) {
			if(typeof c1 == "object" && typeof c2 == "object"){
				for(var key in c2) {
					c1[key] = c2[key];
				}
			}
			return c1;
		},
		isObject: function(o) {
			return (typeof o == "object");
		},
		isArray: function(o) {
			return (o instanceof Array);
		},
		isFunction: function(o) {
			return (typeof o == "function");
		},
		isString: function(o) {
			return (typeof o == "string");
		},
		isNumber: function(o) {
			return (typeof o == "number");
		},
		/*
			根据字符串类型获取一个类
		*/
		getClass: function(name) {
			if(typeof name !== "string")
				return name
		
			var v = name.split('.'),
				o = window[v[0]],
				i = 1,
				len = v.length;
			
			for(; i < len ; i++) {
				if(!o) return o
				o = o[v[i]] ;
			}
			return o;
		},
		/* 定义名字空间 */
		namespace: function(name) {
		
			if(typeof name !== "string")
				return name
		
			var v = name.split('.'),
				o = window[v[0]] = window[v[0]] || {},
				i = 1,
				len = v.length;
			
			for(; i < len ; i++) {
				o = o[v[i]] = o[v[i]] || {};
			}
			return o;
		},
		ns: function(){
			return this.namespace.apply(this,arguments);
		}
	}
	
	/*
		接口类  下面接口类是设计模式书中的一个例子 copy过来的
	*/
	
	var Interface = function(name, methods) {
		
		var i = 0,
			len = methods.length;
		
		this.name = name;
		this.methods = [];
		
		for (; i < len; i++) {
			this.methods.push(methods[i]);
		}
	}
	/*
		检测接口方法是否被实现
	*/
	Interface.ensureImplements = function(object) {
		
		var i = 1,
			len = arguments.length,
			j = 0,
			menthodsLen;
		for (; i < len; i++) {
			for (methodsLen = arguments[i].methods.length; j < methodsLen; j++) {
				var method = arguments[i].methods[j];
				if (!object[method] || typeof object[method] !== 'function') {
					throw new Error("类" + object.className + "未实现" + arguments[i].name + " 接口方法 " + method);
				}
			}
		}
	}
	
	/*
		类式继承
	*/
	function extend(subClass,superClass) {
		var F = function(){};
		F.prototype = superClass.prototype;
		subClass.prototype = new F();
		
		util.applyIf(subClass.prototype,new F())
		
		subClass.prototype.constructor = subClass;
		
		if (superClass.prototype.constructor == Object.prototype.constructor) {
			superClass.prototype.constructor = superClass;
		}
		/*
			为子类添加静态属性 superclass 指向父类
		*/
		subClass.superclass = superClass.prototype;
		/*
			为子类添加一个方法 callParent 调用父类的当前函数
		*/
		subClass.prototype.callParent = function(cfg) {
			var method,methodName;
			method = this.callParent.caller;
			for (var key in this) {
				if (this[key] === method) {
					methodName = key
				}
			}
			superClass.prototype[methodName].apply(this,cfg)
		}
		
	}
	
	/*
		添加别名到 widgetMap 对象中
	*/
	function setWidget(name,cls) {
		var n = name;
		if (name.indexOf('widget.') > -1) {
			n = name.substring(7,name.length);
		}
		widgetMap[n] = cls;
	}
	
	var pub = {
	
		/*
			使用字符串格式名称创建类
		*/
		create: function(name, cfg) {
			var clazz = util.getClass(name);
			return new clazz(cfg);