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 相关文章推荐
asp.net+js 实现无刷新上传解析csv文件的代码
May 17 Javascript
jquery异步循环获取功能实现代码
Sep 19 Javascript
jQuery获取样式中的背景颜色属性值/颜色值
Dec 17 Javascript
jQuery的:parent选择器定义和用法
Jul 01 Javascript
JavaScript针对网页节点的增删改查用法实例
Feb 02 Javascript
基于jQuery实现复选框是否选中进行答题提示
Dec 10 Javascript
jQuery实现百叶窗焦点图动画效果代码分享(附源码下载)
Mar 14 Javascript
使用JavaScript实现ajax的实例代码
May 11 Javascript
JS操作input标签属性checkbox全选的实现代码
Mar 02 Javascript
jQuery实现字体颜色渐变效果的方法
Mar 29 jQuery
js下载文件并修改文件名
May 08 Javascript
arctext.js实现文字平滑弯曲弧形效果的插件
May 13 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
生成缩略图
2006/10/09 PHP
一个更简单的无限级分类菜单代码
2007/01/16 PHP
比较全的PHP 会话(session 时间设定)使用入门代码
2008/06/05 PHP
php中使用gd库实现下载网页中所有图片
2015/05/12 PHP
javascript Xml增删改查(IE下)操作实现代码
2009/01/30 Javascript
jquery 选择器部分整理
2009/10/28 Javascript
常见浏览器多长时间会提示“脚本运行时间过长”总结
2014/04/29 Javascript
js 加密压缩出现bug解决方案
2014/11/25 Javascript
Bootstrap树形组件jqTree的简单封装
2016/01/25 Javascript
vue组件实现文字居中对齐的方法
2017/08/23 Javascript
Node.js利用断言模块assert进行单元测试的方法
2017/09/28 Javascript
jQuery实现html双向绑定功能示例
2017/10/09 jQuery
vue2手机APP项目添加开屏广告或者闪屏广告
2017/11/28 Javascript
Webpack中publicPath路径问题详解
2018/05/03 Javascript
4个顶级开源JavaScript图表库
2018/09/29 Javascript
使用layer弹窗,制作编辑User信息页面的方法
2019/09/27 Javascript
Vue使用vue-recoure + http-proxy-middleware + vuex配合promise实现基本的跨域请求封装
2019/10/21 Javascript
Array.filter中如何正确使用Async
2020/11/04 Javascript
[03:22]DSPL第一期精彩集锦:酷炫到底!
2014/11/07 DOTA
python获取指定路径下所有指定后缀文件的方法
2015/05/26 Python
python简单读取大文件的方法
2016/07/01 Python
简单谈谈Python中的几种常见的数据类型
2017/02/10 Python
pandas groupby 分组取每组的前几行记录方法
2018/04/20 Python
Python爬虫之正则表达式的使用教程详解
2018/10/25 Python
Python连接Oracle之环境配置、实例代码及报错解决方法详解
2020/02/11 Python
jupyter notebook快速入门及使用详解
2020/11/13 Python
LocalStorage记住用户和密码功能
2017/07/24 HTML / CSS
HTML table 表格边框的实现思路
2019/10/12 HTML / CSS
美国在线家居装饰店:Belle&June
2018/10/24 全球购物
介绍一下mysql的日期和时间函数
2013/03/28 面试题
shell变量的作用空间是什么
2013/08/17 面试题
装修设计师求职信
2014/02/26 职场文书
新员工考核评语
2014/12/31 职场文书
北大自主招生自荐信
2015/03/04 职场文书
详解Java ES多节点任务的高效分发与收集实现
2021/06/30 Java/Android
Spring Data JPA框架Repository自定义实现
2022/04/28 Java/Android