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与CSS复习(三)
Jun 29 Javascript
利用jQuery实现可输入搜索文字的下拉框
Oct 23 Javascript
javascript的数组和常用函数详解
May 09 Javascript
jQuery中innerHeight()方法用法实例
Jan 19 Javascript
Sortable.js拖拽排序使用方法解析
Nov 04 Javascript
webpack入门必知必会
Jan 16 Javascript
浅谈angular2的http请求返回结果的subcribe注意事项
Mar 01 Javascript
layui分页效果实现代码
May 19 Javascript
Vue.js的动态组件模板的实现
Nov 26 Javascript
实例分析Array.from(arr)与[...arr]到底有何不同
Apr 09 Javascript
vue(2.x,3.0)配置跨域代理
Nov 27 Javascript
vue+element使用动态加载路由方式实现三级菜单页面显示的操作
Aug 04 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
2020年4月新番动漫目录 官方宣布4月播出的作品一览
2020/03/08 日漫
基于PHP的cURL快速入门教程 (小偷采集程序)
2011/06/02 PHP
PHP函数篇详解十进制、二进制、八进制和十六进制转换函数说明
2011/12/05 PHP
PHP设计模式之装饰者模式
2012/02/29 PHP
php进程间通讯实例分析
2016/07/11 PHP
了解jQuery技巧来提高你的代码
2010/01/08 Javascript
清空上传控件input file的值
2010/07/03 Javascript
关于javascript模块加载技术的一些思考
2014/11/28 Javascript
移动端H5开发 Turn.js实现很棒的翻书效果
2016/06/20 Javascript
Bootstrap 最常用的JS插件系列总结(图片轮播、标签切换等)
2016/07/14 Javascript
JavaScript中自带的 reduce()方法使用示例详解
2016/08/10 Javascript
jquery.form.js异步提交表单详解
2017/04/25 jQuery
node.js用fs.rename强制重命名或移动文件夹的方法
2017/12/27 Javascript
解析vue data不可以使用箭头函数问题
2018/07/03 Javascript
Vue中JS动画与Velocity.js的结合使用
2019/02/13 Javascript
微信小程序开发之左右分栏效果的实例代码
2019/05/20 Javascript
JS回调函数简单易懂的入门实例分析
2019/09/29 Javascript
Vue如何基于es6导入外部js文件
2020/05/15 Javascript
[04:28]2014DOTA2国际邀请赛 采访小兔子LGD挺进钥匙体育馆
2014/07/14 DOTA
python复制文件代码实现
2013/12/23 Python
简述Python中的面向对象编程的概念
2015/04/27 Python
Python、PyCharm安装及使用方法(Mac版)详解
2017/04/28 Python
Windows系统下多版本pip的共存问题详解
2017/10/10 Python
名片管理系统python版
2018/01/11 Python
python队列Queue的详解
2019/05/10 Python
使用PyCharm进行远程开发和调试的实现
2019/11/04 Python
简单了解python调用其他脚本方法实例
2020/03/26 Python
Belle Maison倍美丛官网:日本千趣会旗下邮购网站
2016/07/22 全球购物
西班牙鞋子和箱包在线销售网站:zapatos.es
2020/02/17 全球购物
意大利时尚奢侈品店:D’Aniello Boutique
2021/01/19 全球购物
华为python面试题
2016/05/03 面试题
绿化工程实施方案
2014/03/17 职场文书
人资专员岗位职责
2014/04/04 职场文书
入党积极分子十八届四中全会思想汇报
2014/10/23 职场文书
施工员岗位职责
2015/02/10 职场文书
导游词范文
2015/02/13 职场文书