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 相关文章推荐
jQuery删除节点的三个方法即remove()detach()和empty()
Dec 27 Javascript
jquery.post用法之type设置问题
Feb 24 Javascript
javascript setinterval 的正确语法如何书写
Jun 17 Javascript
讲解JavaScript中for...in语句的使用方法
Jun 03 Javascript
javascript数据结构之双链表插入排序实例详解
Nov 25 Javascript
js实现将选中内容分享到新浪或腾讯微博
Dec 16 Javascript
JavaScript焦点事件、鼠标事件和滚轮事件使用详解
Jan 15 Javascript
jquery 重写 ajax提交并判断权限后 使用load方法报错解决方法
Jan 19 Javascript
jQuery 的 ready()的纯js替代方法
Nov 20 Javascript
vue实现样式之间的切换及vue动态样式的实现方法
Dec 19 Javascript
vue+element的表格实现批量删除功能示例代码
Aug 17 Javascript
JS实现audio音频剪裁剪切复制播放与上传(步骤详解)
Jul 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
PHP 获取MSN好友列表的代码(2009-05-14测试通过)
2009/09/09 PHP
PHP详解ASCII码对照表与字符转换
2011/12/05 PHP
PHP中file_get_contents函数抓取https地址出错的解决方法(两种方法)
2015/09/22 PHP
JavaScript-世界上误解最深的语言分析
2007/08/12 Javascript
Jquery AJAX 用于计算点击率(统计)
2010/06/30 Javascript
js页面跳转常用的几种方式
2010/11/25 Javascript
jquery子元素过滤选择器使用示例
2013/06/24 Javascript
js全屏显示显示代码的三种方法
2013/11/11 Javascript
Javascript中的回调函数和匿名函数的回调示例介绍
2014/05/12 Javascript
javascript中expression的用法整理
2014/05/13 Javascript
JS辨别访问浏览器判断是android还是ios系统
2014/08/19 Javascript
javascript基本算法汇总
2016/03/09 Javascript
Function.prototype.apply()与Function.prototype.call()小结
2016/04/27 Javascript
JS简单实现DIV相对于浏览器固定位置不变的方法
2016/06/17 Javascript
浅谈jQuery中ajaxPrefilter的应用
2016/08/01 Javascript
再谈Javascript中的异步以及如何异步
2016/08/19 Javascript
详解Html a标签中href和onclick用法、区别、优先级别
2017/01/16 Javascript
解决Vue2.x父组件与子组件之间的双向绑定问题
2018/03/06 Javascript
vue实现微信获取用户信息的方法
2019/03/21 Javascript
OpenLayers实现图层切换控件
2020/09/25 Javascript
vue3.0中友好使用antdv示例详解
2021/01/05 Vue.js
Python2.x版本中cmp()方法的使用教程
2015/05/14 Python
利用Python学习RabbitMQ消息队列
2015/11/30 Python
Android应用开发中Action bar编写的入门教程
2016/02/26 Python
Python编程实现及时获取新邮件的方法示例
2017/08/10 Python
django请求返回不同的类型图片json,xml,html的实例
2018/05/22 Python
python 多线程对post请求服务器测试并发的方法
2019/06/13 Python
2021年值得向Python开发者推荐的VS Code扩展插件
2021/01/25 Python
美国网上订购鲜花:FTD
2016/09/23 全球购物
美国知名的网上鞋类及相关服装零售商:Shoes.com
2017/05/06 全球购物
Allsole美国/加拿大:英国一家专门出售品牌鞋子的网站
2018/10/21 全球购物
材料成型专业个人求职信范文
2013/09/25 职场文书
2014年自愿离婚协议书范本
2014/09/25 职场文书
会议主持词开场白
2015/05/28 职场文书
MySQL系列之三 基础篇
2021/07/02 MySQL
Python实现对齐打印 format函数的用法
2022/04/28 Python