Javascript面向对象扩展库代码分享


Posted in Javascript onMarch 27, 2012

lang.js库提供了包和类的定义、类的继承与混合(mixin)、函数重载等功能,基本可满足大多数面向对象设计的需求。同时支持基于链式的定义方式,让库在使用时更加规范和便捷。下面首先通过简单的例子演示了lang.js的基本功能,之后给出了lang.js的源码及注释。
一.功能介绍
“lang”作为框架的全局定义,其中包括了四个方法:
lang.Package(string name) //用于定义包(默认会暴露到全局)
lang.Class(string name[, object config], object classBody) //用于定义类
lang.Object(string name | object body) //用于定义支持重载函数的普通对象
lang.Function(string name | object body) //用于定义重载函数

var lang = (function(){ 
/*********************************** 
Javascript面向对象扩展库(lang.js v1.0) 
By: X!ao_f 
QQ: 120000512 
Mail: xiao_f.mail#163.com 
************************************/ 
var customToString = function(){ 
return '[' + this.Type.type + ' ' + this.Type.name + ']'; 
} 
//支持重载的方法定义 
var createMethod = (function(){ 
//创建一个代理函数 
var createMethodProxy = function(context, name){ 
//当调用重载的函数时,首先会执行该函数分析传入的参数,进行匹配和转发 
var method = function(){ 
//在第一次调用时初始化,将映射信息缓存 
if(!method.__initialized__){ 
initializeMethod(method); 
} 
//将参数类型拼接成函数签名 
var signature; 
if(arguments.length){ 
var list = []; 
for(var i=0; i<arguments.length; i++){ 
var typename; 
var argument = arguments[i]; 
if(argument === undefined || argument === null){ 
typename = 'object'; 
}else if(argument instanceof Array){ 
typename = 'array'; 
}else if(argument instanceof Date){ 
typename = 'date'; 
}else{ 
typename = typeof argument; 
if(typename == 'object'){ 
if('Class' in argument){ 
typename = argument.Class.Type.name; 
}else if('nodeType' in argument){ 
typename = 'element'; 
} 
} 
} 
list.push(typename); 
} 
signature = list.join(','); 
}else{ 
signature = ''; 
} 
//如果常规缓存中存在匹配的签名,直接调用 
if(method.__overloads__[signature]){ 
return method.__overloads__[signature].apply(this, arguments); 
}else{ 
//缓存中不存在时,尝试利用正则进行模糊匹配 
//首先判断模糊匹配缓存中是否存在记录,如存在直接调用 
if(method.__overloadsCache__[signature]){ 
return method.__overloadsCache__[signature].apply(this, arguments); 
} 
//循环匹配 
for(var i=0; i<method.__overloadsRegExp__.length; i++){ 
//如果匹配成功,将映射关系存入模糊匹配缓存,同时调用并返回 
if(method.__overloadsRegExp__[i].regexp.test(signature)){ 
method.__overloadsCache__[signature] = method.__overloadsRegExp__[i].fn; 
return method.__overloadsRegExp__[i].fn.apply(this, arguments); 
} 
} 
//如果依然无法找到对应的函数,判断是否存在默认函数 
if(method.__overloads__['default']){ 
return method.__overloads__['default'].apply(this, arguments); 
}else if(method.__overloads__['']){ 
return method.__overloads__[''].apply(this, arguments); 
}else{ 
alert('Error: '+method.Type.name+'('+signature+') is undefined.'); 
} 
} 
}; 
//内置对象 
method.__context__ = context; 
method.__functions__ = {}; 
method.toString = customToString; 
//自描述信息 
method.Type = { 
name: name, 
Method: method, 
type: 'method' 
}; 
return method; 
} 
//初始化 
var initializeMethod = function(method){ 
//基础签名缓存 
method.__overloads__ = {}; 
//模糊匹配正则缓存 
method.__overloadsRegExp__ = []; 
//模糊匹配结果缓存 
method.__overloadsCache__ = {}; 
//例举所有定义的函数 
for(var signature in method.__functions__){ 
var fn = method.__functions__[signature]; 
var params = signature.substring(signature.indexOf('(') + 1, signature.length - 1); 
var pure = !/[\*\+\?\{]/.test(params); 
//如果不存在通配符直接保存到基础签名缓存 
if(pure){ 
method.__overloads__[params] = fn; 
}else{ 
//生成模糊匹配正则 
var regexp = '^' + params 
.replace(/([\w\.]+)(\{.*?\})?/g, '($1(,|$))$2') 
.replace(/\./g, '\\.') 
.replace(/((\()var(\())/g, '$2\\w+$3') 
.replace(/,\(/g, '(') + '$'; 
method.__overloadsRegExp__.push({ regexp: new RegExp(regexp), fn: fn }); 
} 
} 
method.__initialized__ = true; 
} 
//返回外部的定义函数 
return function(signature, fn, comp){ 
//如果传入的为一个对象,视为定义匿名方法 
if(typeof signature == 'object'){ 
var context = {}; 
var method; 
for(var key in signature){ 
method = createMethod.call(context, 'anonymous'+key, signature[key]); 
} 
return method; 
} 
signature = signature.replace(/\s+/g, ''); 
var index = signature.indexOf('('); 
var name = index > -1 ? signature.substring(0, signature.indexOf('(')) : signature; 
var context = this; 
var method = context[name]; 
//上下文中不存在函数定义,视为第一次定义 
if(method === undefined){ 
context[name] = method = createMethodProxy(context, name); 
}else if(!method.Type || method.Type.type!='method'){ 
//上下文存在的函数是原生函数,将这个函数作为默认函数存入列表 
var temp = method; 
context[name] = method = createMethodProxy(context, name); 
method.__functions__[name + '()'] = temp; 
}else{ 
//如果上下文不同,创建新的重载方法并将已经存在的函数复制,这里主要解决类继承中子类与父类冲突的问题 
//如果上下文相同,直接将初始化标记设为false,待下次调用时重新初始化 
if(method.__context__ !== context){ 
var temp = method; 
context[name] = method = createMethodProxy(context); 
for(var sign in temp.__functions__){ 
method.__functions__[sign] = temp.__functions__[sign]; 
} 
}else{ 
method.__initialized__ = false; 
} 
} 
//将本次定义的函数添加到函数列表 
//先入为主策略 
if(comp){ 
if(fn.__functions__){ 
for(var key in fn.__functions__){ 
if(key in method.__functions__){ 
method.__functions__[key].__overridden__ = fn; 
}else{ 
method.__functions__[key] = fn; 
} 
} 
}else{ 
if(signature in method.__functions__){ 
method.__functions__[signature].__overridden__ = fn; 
}else{ 
method.__functions__[signature] = fn; 
} 
} 
}else{ 
//后入为主策略 
if(fn.__functions__){ 
for(var key in fn.__functions__){ 
if(key in method.__functions__){ 
fn.__functions__[key].__overridden__ = method; 
} 
method.__functions__[key] = fn.__functions__[key]; 
} 
}else{ 
if(signature in method.__functions__){ 
fn.__overridden__ = method; 
} 
method.__functions__[signature] = fn; 
} 
} 
if(this.Type && this.Type.type == 'package'){ 
return this; 
}else{ 
return method; 
} 
}; 
})(); 
//类定义函数 
var createClass = (function(){ 
var slice = Array.prototype.slice; 
var emptyFn = function(){}; 
var createClass = function(name){ 
return function(){ 
this[name].apply(this, slice.call(arguments, 0)); 
}; 
} 
//用于调用被重写函数 
var baseCaller = function(){ 
if(arguments.length){ 
var args = slice.call(arguments, 0); 
return baseCaller.caller.__overridden__.apply(this, args); 
}else{ 
return baseCaller.caller.__overridden__.call(this); 
} 
} 
//用于调用自身重载构造函数 
var selfCaller = function(){ 
if(arguments.length){ 
var args = slice.call(arguments, 0); 
return selfCaller.caller.__self__.apply(this, args); 
}else{ 
return selfCaller.caller.__self__.call(this); 
} 
} 
var filter = {prototype:true, Type:true}; 
//快速浅拷贝 
function clone(a){ 
var fn = function(){}; 
fn.prototype = a; 
return new fn; 
} 
//对象复制,替换存在的(后入为主) 
function replace(base, self){ 
for(var key in self){ 
if(!(key in filter)){ 
if(typeof self[key] == 'function'){ 
//如果子类函数包含重载签名或父类函数已经重载 
if(key.indexOf('(') > -1 || (base[key] && base[key].__functions__)){ 
createMethod.call(base, key, self[key]); 
}else{ 
//常规函数定义 
if(key in base){ 
//记录重写信息 
self[key].__overridden__ = base[key]; 
} 
base[key] = self[key]; 
} 
}else{ 
base[key] = self[key]; 
} 
} 
} 
} 
//对象复制,只取补集(先入为主) 
function complement(self, base){ 
for(var key in base){ 
if(!(key in filter)){ 
if(typeof base[key] == 'function'){ 
if(key.indexOf('(') > -1 || (self[key] && self[key].__functions__)){ 
createMethod.call(self, key, base[key], true); 
}else{ 
if(key in self){ 
//记录重写信息 
self[key].__overridden__ = base[key]; 
}else{ 
self[key] = base[key]; 
} 
} 
}else if(!(key in self)){ 
self[key] = base[key]; 
} 
} 
} 
} 
return function(){ 
//处理参数 
if(this.Type && this.Type.type == 'package'){ 
if(arguments.length == 2){ 
var name = arguments[0]; 
var body = arguments[1]; 
}else{ 
var name = arguments[0]; 
var config = arguments[1]; 
var body = arguments[2]; 
} 
}else{ 
if(arguments.length == 1){ 
var name = 'Anonymous'; 
var body = arguments[0]; 
}else{ 
var name = 'Anonymous'; 
var config = arguments[0]; 
var body = arguments[1]; 
} 
} 
//创建类的基础函数 
var clazz = createClass(name); 
//获取父类信息 
var baseClass; 
if(config && config.extend){ 
baseClass = config.extend; 
} 
//如果传入的主体为函数,取其返回值 
if(typeof body == 'function'){ 
body = body(clazz); 
} 
//处理静态成员 
if(body.Static){ 
complement(clazz, body.Static); 
delete body.Static; 
body = body.Public||body; 
}else{ 
body = body.Public||body; 
} 
//处理继承 
if(baseClass){ 
//通过快速浅拷贝复制父类成员 
clazz.prototype = clone(baseClass.prototype); 
//继承静态成员 
complement(clazz, baseClass); 
//继承类成员 
complement(clazz.prototype, body); 
}else{ 
//不存在继承 
clazz.prototype = {}; 
complement(clazz.prototype, body); 
} 
//处理混合 
if(config && config.mixin){ 
var mixin = config.mixin; 
if(mixin instanceof Array){ 
for(var i=0; i<mixin.length; i++){ 
replace(clazz.prototype, mixin[i]); 
} 
}else{ 
replace(clazz.prototype, mixin); 
} 
} 
//添加内置函数 
clazz.prototype.base = baseCaller; 
clazz.prototype.self = selfCaller; 
clazz.prototype.constructor = clazz; 
clazz.prototype.toString = customToString; 
clazz.toString = customToString; 
clazz.prototype.Class = clazz; 
if(clazz.prototype[name]){ 
var constructor = clazz.prototype[name]; 
if(constructor.__functions__){ 
for(var key in constructor.__functions__){ 
//存在重载时,添加自身引用,用于通过this.self调用重载构造函数 
constructor.__functions__[key].__self__ = constructor; 
//存在继承时,将父类的构造函数作为被重写的函数,配置给当前类的构造函数 
//用于通过base调用父类构造函数 
if(baseClass){ 
constructor.__functions__[key].__overridden__ = baseClass.prototype[baseClass.Type.shortName]; 
} 
} 
}else if(baseClass){ 
clazz.prototype[name].__overridden__ = baseClass.prototype[baseClass.Type.shortName]; 
} 
}else{ 
clazz.prototype[name] = emptyFn; 
} 
//类型自描述信息 
//如果当前上下文是一个包,将类添加到包中 
if(this.Type && this.Type.type == 'package'){ 
clazz.Type = { 
type:'class', 
name: this.Type.name+'.'+name, 
shortName: name, 
Package: this, 
Class: clazz, 
baseClass: baseClass 
} 
clazz.prototype.Type = { 
type: 'object', 
name: this.Type.name+'.'+name 
} 
//将类添加到包 
this[name] = clazz; 
//调用静态构造函数 
if(name in clazz){ 
clazz[name].call(clazz); 
} 
//返回this用于链式调用 
return this; 
}else{ 
//上下文不是包则直接返回 
clazz.Type = { 
type:'class', 
name: name, 
shortName: name, 
Class: clazz, 
baseClass: baseClass 
} 
clazz.prototype.Type = { 
type: 'object', 
name: name, 
baseClass: baseClass 
} 
if(name in clazz){ 
clazz[name].call(clazz); 
} 
return clazz; 
} 
}; 
})(); 
//用于创建支持重载的普通对象 
var createObject = function(objects, config){ 
var target; 
if(this.Type && this.Type.type == 'package'){ 
target = this; 
}else{ 
target = {}; 
} 
if(typeof objects == 'string'){ 
target = this[objects] = {}; 
objects = config; 
}else if(typeof objects == 'function'){ 
objects = objects(); 
} 
for(var key in objects){ 
if(typeof objects[key] == 'function' && (key.indexOf('(') > -1 || typeof target[key] == 'function')){ 
createMethod.call(target, key, objects[key]); 
}else{ 
target[key] = objects[key]; 
} 
} 
if(this.Type && this.Type.type == 'package'){ 
return this; 
}else{ 
return target; 
} 
}; 
//用于创建包 
var createPackage = (function(){ 
var root = this; 
return function(package){ 
var name = []; 
var path = package.split('.'); 
var parent = root; 
for(var i=0; i<path.length; i++){ 
name.push(path[i]); 
if(parent[path[i]]){ 
parent = parent[path[i]]; 
}else{ 
var pack = { 
Class: createClass, 
Object: createObject, 
Function: createMethod, 
Package: createPackage, 
toString: customToString 
}; 
pack.Type = { 
type: 'package', 
Package: pack, 
name: name.join('.') 
} 
parent = parent[path[i]] = pack; 
} 
} 
return parent; 
} 
})(); 
//默认将Package暴露 
window.Package = createPackage; 
return { 
Package: createPackage, 
Class: createClass, 
Function: createMethod, 
Object: createObject 
}; 
})();

结束语:
到这里,lang.js的应用和原理就介绍完毕了,该库在主流浏览器中均已测试通过,
如果想使用lang.js,可以在这里免费下载,如发现什么问题,或有好的建议可以反馈给我。
Javascript 相关文章推荐
javascript 学习之旅 (1)
Feb 05 Javascript
拖动table标题实现改变td的大小(css+js代码)
Apr 16 Javascript
获取元素距离浏览器周边的位置的方法getBoundingClientRect
Apr 17 Javascript
Javascript合并表格中具有相同内容单元格示例
Aug 11 Javascript
jquery代码实现简单的随机图片瀑布流效果
Apr 20 Javascript
深入浅析JavaScript字符串操作方法 slice、substr、substring及其IE兼容性
Dec 16 Javascript
Vue生命周期示例详解
Apr 12 Javascript
微信小程序自动客服功能
Nov 02 Javascript
微信小程序dom操作的替代思路实例分析
Dec 06 Javascript
Bootstrap实现模态框效果
Sep 30 Javascript
js常用方法、检查是否有特殊字符串、倒序截取字符串操作完整示例
Jan 26 Javascript
Vue自定义组件的四种方式示例详解
Feb 28 Javascript
用Javascript实现Windows任务管理器的代码
Mar 27 #Javascript
推荐30个新鲜出炉的精美 jQuery 效果
Mar 26 #Javascript
获取服务器传来的数据 用JS去空格的正则表达式
Mar 26 #Javascript
jquery星级插件、支持页面中多次使用
Mar 25 #Javascript
JQuery实现倒计时按钮的实现代码
Mar 23 #Javascript
JQuery防止退格键网页后退的实现代码
Mar 23 #Javascript
jQuery中将函数赋值给变量的调用方法
Mar 23 #Javascript
You might like
mysql_num_rows VS COUNT 效率问题分析
2011/04/23 PHP
PHP实现文件上传功能实例代码
2017/05/18 PHP
ExtJs GridPanel简单的增删改实现代码
2010/08/26 Javascript
关于Mozilla浏览器不支持innerText的解决办法
2011/01/01 Javascript
从阶乘函数对比Javascript和C#的异同
2012/05/31 Javascript
Ext JS 4实现带week(星期)的日期选择控件(实战一)
2013/08/21 Javascript
js调用css属性写法
2013/09/21 Javascript
js设置组合快捷键/tabindex功能的方法
2013/11/21 Javascript
javascript实现动态改变层大小的方法
2015/05/14 Javascript
Angularjs中使用Filters详解
2016/03/11 Javascript
JQuery解析XML数据的几个简单实例
2016/05/18 Javascript
JQuery学习总结【二】
2016/12/01 Javascript
JS简单验证上传文件类型的方法
2017/04/17 Javascript
jquery在vue脚手架中的使用方式示例
2017/08/29 jQuery
JS库particles.js创建超炫背景粒子插件(附源码下载)
2017/09/13 Javascript
JS实现带导航城市列表以及输入搜索功能
2018/01/04 Javascript
在vscode里使用.vue代码模板的方法
2018/04/28 Javascript
Vue自定义toast组件的实例代码
2018/08/15 Javascript
[01:06:26]全国守擂赛第二周 Team Coach vs DeMonsTer
2020/04/28 DOTA
在windows下Python打印彩色字体的方法
2018/05/15 Python
详解Django 时间与时区设置问题
2019/07/23 Python
Windows系统Python直接调用C++ DLL的方法
2019/08/01 Python
Python random库使用方法及异常处理方案
2020/03/02 Python
TensorFlow keras卷积神经网络 添加L2正则化方式
2020/05/22 Python
python代码中怎么换行
2020/06/17 Python
python学习笔记之多进程
2020/08/06 Python
详解rem 适配布局
2018/10/31 HTML / CSS
HTML5和CSS3实例教程总结(推荐)
2016/07/18 HTML / CSS
利用Storage Event实现页面间通信的示例代码
2018/07/26 HTML / CSS
美国Curacao百货连锁店网站:iCuracao.com
2019/07/20 全球购物
大学三年的自我评价
2013/12/25 职场文书
精通CAD能手自荐书
2014/01/31 职场文书
《油菜花开了》教学反思
2014/02/22 职场文书
违反交通安全法检讨书
2014/10/24 职场文书
见习报告格式要求
2014/11/04 职场文书
讲解MySQL增删改操作
2022/05/06 MySQL