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 相关文章推荐
js资料toString 方法
Mar 13 Javascript
JavaScript 事件记录使用说明
Oct 20 Javascript
js的.innerHTML = &quot;&quot;IE9下显示有错误的解决方法
Sep 16 Javascript
利用jq让你的div居中的好方法分享
Nov 21 Javascript
深入理解angularjs过滤器
May 25 Javascript
jQuery实现ToolTip元素定位显示功能示例
Nov 23 Javascript
滚动条的监听与内容随着滚动条动态加载的实现
Feb 08 Javascript
在js代码拼接dom对象到页面上的模板总结
Oct 21 Javascript
es6基础学习之解构赋值
Dec 10 Javascript
vue slot与传参实例代码讲解
Apr 28 Javascript
原生JavaScript实现日历功能代码实例(无引用Jq)
Sep 23 Javascript
JavaScript实现多文件下载方法解析
Aug 07 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的数据库抽象层函数库
2006/10/09 PHP
PHP sleep()函数, usleep()函数
2016/08/25 PHP
PHP进程通信基础之信号量与共享内存通信
2017/02/19 PHP
jQuery EasyUI API 中文文档 - Calendar日历使用
2011/10/19 Javascript
jQuery常用操作方法及常用函数总结
2014/06/19 Javascript
js超时调用setTimeout和间歇调用setInterval实例分析
2015/01/28 Javascript
jquery转盘抽奖功能实现
2015/11/13 Javascript
一波JavaScript日期判断脚本分享
2016/03/06 Javascript
详解handlebars+require基本使用方法
2016/12/21 Javascript
深入学习jQuery中的data()
2016/12/22 Javascript
基于Bootstrap分页的实例讲解(必看篇)
2017/07/04 Javascript
Jquery获取radio选中值实例总结
2019/01/17 jQuery
微信小程序实现下滑到底部自动翻页功能
2020/03/07 Javascript
[01:00:14]DOTA2官方TI8总决赛纪录片 真视界True Sight
2019/01/16 DOTA
Python Web框架Flask中使用新浪SAE云存储实例
2015/02/08 Python
python基础之入门必看操作
2017/07/26 Python
Python 判断图像是否读取成功的方法
2019/01/26 Python
python获取地震信息 微信实时推送
2019/06/18 Python
超简单的Python HTTP服务
2019/07/22 Python
Python 闭包,函数分隔作用域,nonlocal声明非局部变量操作示例
2019/10/14 Python
python__name__原理及用法详解
2019/11/02 Python
编写python代码实现简单抽奖器
2020/10/20 Python
Python urlopen()参数代码示例解析
2020/12/10 Python
详解Css3新特性应用之过渡与动画
2017/01/10 HTML / CSS
你可能不熟练的十个前端HTML5经典面试题
2018/07/03 HTML / CSS
理肤泉英国官网:La Roche-Posay英国
2019/01/14 全球购物
法国体育用品商店:GO Sport
2019/10/23 全球购物
会计电算化大学生职业规划书
2014/02/05 职场文书
《广玉兰》教学反思
2014/04/14 职场文书
工厂搬迁方案
2014/05/11 职场文书
元旦主持词开场白
2015/05/29 职场文书
运动会通讯稿200字
2015/07/20 职场文书
幼儿园2016年圣诞活动总结
2016/03/31 职场文书
Nginx服务器如何设置url链接
2021/03/31 Servers
Redisson实现Redis分布式锁的几种方式
2021/08/07 Redis
HTML基本元素标签介绍
2022/02/28 HTML / CSS