Javascript面向对象扩展库
最近一直在用js做项目,遇到了许多需要应用面向对象来设计的功能,由于js对OOP的原生支持还不是很完善,所以就写了一个面向对象的扩展库用做底层支持,现在把它单独整理出来,完善了一些功能,在这里分享一下。
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) //用于定义重载函数
//1.基本的包和类的定义:
//首先通过全局函数Package定义一个包,下面可通过链式调用向包中定义类、对象或函数。
Package('com.site').
Class('Base',{
Base: function(tagName){
this.element = document.createElement(tagName);
},
add: function(child){
this.element.appendChild(child);
},
show: function(){
alert('I am Base!');
}
}).
Class('Control', {
Control: function(){
//do soming
}
});
alert(com.site);
alert(com.site.Base);
alert(com.site.Control);
//2.普通对象定义
//一个不需初始化的类,可直接定义成普通对象
Package('com.site.util').
Object({
ModelA: {
say: function(){
alert('ModelA: Hello!');
}
},
ModelB: {
print: function(){
alert('ModelB: ' + this.Class.Type.name);
}
}
});
com.site.util.ModelA.say();
//3.类的继承
//像很多面向对象语言一样,这里约定一个类只能拥有一个父类。但是可以通过mixin混合多个普通对象。
//在子类的构造函数中可以通过this.base访问父类的构造函数。
//如子类定义了与父类相同函数,父类函数将被重写,这里同样可以通过this.base调用父类被重写的函数。
Package('com.site').
Class('Panel', {extend: com.site.Base, mixin:[com.site.util.ModelA, com.site.util.ModelB]}, {
Panel: function(tagName){
//这里使用this.base调用父类构造函数
this.base(tagName);
},
show: function(){
alert('I am Panel!');
this.base();
}
});
var panel = new com.site.Panel("div");
panel.say();
panel.print();
alert(panel.element.outerHTML);
//4.静态成员的定义
/*
程序中可以将类的主体以函数的形式定义,将私有成员定义在函数内部,将公共成员以返回值的形式暴露出来。这种设计模式在很多流行框架中都可以看到,虽然隐藏的成员只能是静态的,不过这也足以满足大部分的需求了。
公有的静态成员可以通过Static标签定义,Static中可包含一个静态构造函数,该函数只会在类第一次创建的时候执行一次。
在运行期间类的内部可以通过this.Class.xxx的形式访问自身的静态成员,(this.Class就是所属类的引用)
*/
Package('com.site').
Class('Button', {extend: com.site.Panel}, function(){
//在这里定义私有静态成员
var tagName = 'BUTTON';
var onclick = function(){
alert('I am a Button!');
}
return {
//这里定义共有静态成员
Static: {
count: 1,
//静态构造函数
Button: function(){
this.createTime = new Date();
}
},
Button: function(text){
this.base(tagName);
this.element.innerHTML = text;
this.element.onclick = onclick;
//调用静态变量
this.Class.count++;
}
};
});
var button = new com.site.Button("Button1");
document.body.appendChild(button.element);
alert(com.site.Button.count);
//5.重载函数的定义
/*
lang.js中对函数重载提供了较完善的支持,在定义函数时可在函数名后面指定参数签名,调用函数时程序根据传入的参数自动匹配转发。
其中支持的类型包括:var,string,number,boolean,array,date,object,function,element和自定义的类(var表示任意类型,element表示DOM元素。)
为了保证灵活性,重载支持通配符功能,遵循正则表达式的规则,可以通过标记“+ * ? {?,?}”来处理不确定参数个数的情况。
重载函数在类的继承过程中是有效的,签名不同的函数不会被重写,被重写的父类重载函数同样支持通过this.base调用。
以下代码为重载在类中应用的例子:
*/
Package('com.site').
Class('Student',{
Static: {
//静态函数重载
'create()': function(){
//这里的this就是类本身,所以可以直接new
return new this('静态', 1);
},
'create(string, number)': function(name, age){
return new this(name, age);
},
'search()': function(){
alert('search(*)');
},
'search(string)': function(name){
alert('search('+name+')');
}
},
//构造函数重载
'Student()': function(){
//利用this.self调用自身构造函数"Student(string, number)"
this.self('未知', 0);
},
'Student(string, number)': function(name, age){
this.name = name;
this.age = age;
},
//普通成员函数重载
'print()': function(){
this.print(this.name ,this.age);
},
'print(string, number)': function(name, age){
alert('name:' + name + ',age:' + age);
},
//支持自定义类的类型
'print(lib.ui.Panel)': function(panel){
this.print(panel, true);
},
'print(lib.ui.Panel, boolean)': function(panel, append){
if(append){
panel.element.innerHTML += this.name;
}else{
panel.element.innerHTML = this.name;
}
}
}).
//继承中对重载的支持
Class('MaleStudent',{extend: com.site.Student},{
Static: {
//重写父类静态函数
'search(string)': function(name){
alert('MaleStudent: search('+name+')');
},
'search(string, number)': function(name, age){
alert('MaleStudent: search('+name+','+age+')');
}
},
'MaleStudent': function(){
//调用父类的构造函数"Student(string, number)"
this.base('未知男同学', 0);
},
'MaleStudent(string, number)': function(name, age){
//调用父类的构造函数"Student(string, number)"
this.base(name, age);
},
//重写了父类的重载函数
'print()': function(){
alert('MaleStudent: name:' + this.name + ',age:' + this.age);
},
'print(string, number)': function(name, age){
//通过this.base调用父类函数"print(string, number)"
this.base('<'+name+'>', '<' + age + '>');
},
//模糊匹配,这个函数可接受一个或多个字符串和零个或多个数字
'print(string+, number*)': function(){
var msg = [];
for(var i=0; i<arguments.length; i++){
msg.push(arguments[i]);
}
alert('print(string+, number*):' + msg.join('+'));
}
});
//创建对象时会自动判断调用的构造函数
var studentA = new com.site.Student();
studentA.print();
var studentB = new com.site.MaleStudent('王小虎', 19);
studentB.print();
studentB.print('小虎', 19);
//这里调用了模糊匹配的重载函数
studentB.print('a','b','c');
studentB.print('x','y','z', 1, 2 ,3);
var studentC = new com.site.MaleStudent();
studentC.print();
//调用静态重载函数
var student = com.site.Student.create();
student.print();
com.site.Student.search();
com.site.Student.search('某同学');
//共有的静态函数会继承到子类,所以MaleStudent也可以create
var maleStudent = com.site.MaleStudent.create('小红', 18);
maleStudent.print();
com.site.MaleStudent.search('小明');
com.site.MaleStudent.search('小明',20);
//6.匿名定义
//有些时候,我们不希望显示的指定一个类或函数的名字,只希望把它保存到变量里面,那么可以通过匿名的方式进行定义。
//1)使用lang.Class创建匿名类
var clazz = lang.Class({
//匿名类的名字统一为Anonymous,所以构造函数的名字也要是Anonymous
Anonymous: function(name){
this.name = name;
},
show: function(){
alert(this.name);
}
});
alert(clazz);
new clazz('匿名类').show();
//2)使用lang.Function创建匿名重载函数
var fn = lang.Function({
'(default)': function(){
var a = [].slice.call(arguments, 0);
alert(a);
},
'(string)': function(a){
alert('(string): ' + a);
},
'(string, number)': function(a, b){
alert('(string, number): ' + a + ':' + b);
},
'(number)': function(a){
alert('(number): ' + a);
}
});
alert(fn);
fn('message');
fn('message', 1);
fn(1);
fn(1,2,3,4,5);
//3)使用lang.Object创建支持重载函数的普通对象
var obj = lang.Object({
name: 'jim',
'write()': function(){
this.write(this.name);
},
'write(string)': function(name){
alert(name);
}
});
obj.write();
obj.write('joe');
//7.综合例子
Package("com.site").
Class('ClassA', {
print: function(){
alert(this.toString());
}
}).
Class('ClassB', {
print: function(){
alert(this.toString());
}
}).
Object({
fn1: function(){
alert(1);
},
fn2: function(){
alert(2);
},
'debug(string)': function(msg){
alert(msg);
},
'debug(string, number)': function(msg, num){
alert(num + ': ' + msg);
},
'debug(com.site.ClassA, string)': function(c, method){
alert('debug ClassA');
c[method]();
},
'debug(com.site.ClassB, string)': function(c, method){
alert('debug ClassB');
c[method]();
},
'debug(element)': function(element){
alert('element:' + element.outerHTML);
}
}).
Object('Web', {
'reload': function(){
alert('reload...');
},
'reload(function)': function(fn){
fn();
}
}).
Package('com.site.util').
Function('myfn(string)', function(name){
alert(name);
}).
Function('myfn(number)', function(num){
alert(num*num);
}).
Class('ClassA', {
ClassA: function(){
alert('ClassA!');
}
});
var div = document.createElement("div");
var span = document.createElement("span");
div.appendChild(span);
com.site.fn1();
com.site.fn2();
com.site.debug('info');
com.site.debug('info', 1);
com.site.debug(new com.site.ClassA(), 'print');
com.site.debug(new com.site.ClassB(), 'print');
com.site.debug(div);
com.site.Web.reload();
com.site.Web.reload(function(){alert('callback');});
com.site.util.myfn('Jim');
com.site.util.myfn(100);
new com.site.util.ClassA();
//8.自描述信息
/*
自描述就是类或对象在定义完成后对自身的信息的描述,常常用于实现一些特殊的功能,库中通过Type"保留字"存储类或包的自描述信息。
下面为使用方法:
*/
var value = com.site.Student;
alert('判断是否一个类:' + (value.Type && value.Type.type == 'class'));
alert('取完整类名:' + com.site.Student.Type.name);
alert('取父类完整类名:' + com.site.MaleStudent.Type.baseClass.Type.name);
alert('取短类名:' + com.site.Student.Type.shortName);
alert('取一个类的包名:' + com.site.Student.Type.Package.Type.name);
//首先通过全局函数Package定义一个包,下面可通过链式调用向包中定义类、对象或函数。
Package('com.site').
Class('Base',{
Base: function(tagName){
this.element = document.createElement(tagName);
},
add: function(child){
this.element.appendChild(child);
},
show: function(){
alert('I am Base!');
}
}).
Class('Control', {
Control: function(){
//do soming
}
});
alert(com.site);
alert(com.site.Base);
alert(com.site.Control);
//2.普通对象定义
//一个不需初始化的类,可直接定义成普通对象
Package('com.site.util').
Object({
ModelA: {
say: function(){
alert('ModelA: Hello!');
}
},
ModelB: {
print: function(){
alert('ModelB: ' + this.Class.Type.name);
}
}
});
com.site.util.ModelA.say();
//3.类的继承
//像很多面向对象语言一样,这里约定一个类只能拥有一个父类。但是可以通过mixin混合多个普通对象。
//在子类的构造函数中可以通过this.base访问父类的构造函数。
//如子类定义了与父类相同函数,父类函数将被重写,这里同样可以通过this.base调用父类被重写的函数。
Package('com.site').
Class('Panel', {extend: com.site.Base, mixin:[com.site.util.ModelA, com.site.util.ModelB]}, {
Panel: function(tagName){
//这里使用this.base调用父类构造函数
this.base(tagName);
},
show: function(){
alert('I am Panel!');
this.base();
}
});
var panel = new com.site.Panel("div");
panel.say();
panel.print();
alert(panel.element.outerHTML);
//4.静态成员的定义
/*
程序中可以将类的主体以函数的形式定义,将私有成员定义在函数内部,将公共成员以返回值的形式暴露出来。这种设计模式在很多流行框架中都可以看到,虽然隐藏的成员只能是静态的,不过这也足以满足大部分的需求了。
公有的静态成员可以通过Static标签定义,Static中可包含一个静态构造函数,该函数只会在类第一次创建的时候执行一次。
在运行期间类的内部可以通过this.Class.xxx的形式访问自身的静态成员,(this.Class就是所属类的引用)
*/
Package('com.site').
Class('Button', {extend: com.site.Panel}, function(){
//在这里定义私有静态成员
var tagName = 'BUTTON';
var onclick = function(){
alert('I am a Button!');
}
return {
//这里定义共有静态成员
Static: {
count: 1,
//静态构造函数
Button: function(){
this.createTime = new Date();
}
},
Button: function(text){
this.base(tagName);
this.element.innerHTML = text;
this.element.onclick = onclick;
//调用静态变量
this.Class.count++;
}
};
});
var button = new com.site.Button("Button1");
document.body.appendChild(button.element);
alert(com.site.Button.count);
//5.重载函数的定义
/*
lang.js中对函数重载提供了较完善的支持,在定义函数时可在函数名后面指定参数签名,调用函数时程序根据传入的参数自动匹配转发。
其中支持的类型包括:var,string,number,boolean,array,date,object,function,element和自定义的类(var表示任意类型,element表示DOM元素。)
为了保证灵活性,重载支持通配符功能,遵循正则表达式的规则,可以通过标记“+ * ? {?,?}”来处理不确定参数个数的情况。
重载函数在类的继承过程中是有效的,签名不同的函数不会被重写,被重写的父类重载函数同样支持通过this.base调用。
以下代码为重载在类中应用的例子:
*/
Package('com.site').
Class('Student',{
Static: {
//静态函数重载
'create()': function(){
//这里的this就是类本身,所以可以直接new
return new this('静态', 1);
},
'create(string, number)': function(name, age){
return new this(name, age);
},
'search()': function(){
alert('search(*)');
},
'search(string)': function(name){
alert('search('+name+')');
}
},
//构造函数重载
'Student()': function(){
//利用this.self调用自身构造函数"Student(string, number)"
this.self('未知', 0);
},
'Student(string, number)': function(name, age){
this.name = name;
this.age = age;
},
//普通成员函数重载
'print()': function(){
this.print(this.name ,this.age);
},
'print(string, number)': function(name, age){
alert('name:' + name + ',age:' + age);
},
//支持自定义类的类型
'print(lib.ui.Panel)': function(panel){
this.print(panel, true);
},
'print(lib.ui.Panel, boolean)': function(panel, append){
if(append){
panel.element.innerHTML += this.name;
}else{
panel.element.innerHTML = this.name;
}
}
}).
//继承中对重载的支持
Class('MaleStudent',{extend: com.site.Student},{
Static: {
//重写父类静态函数
'search(string)': function(name){
alert('MaleStudent: search('+name+')');
},
'search(string, number)': function(name, age){
alert('MaleStudent: search('+name+','+age+')');
}
},
'MaleStudent': function(){
//调用父类的构造函数"Student(string, number)"
this.base('未知男同学', 0);
},
'MaleStudent(string, number)': function(name, age){
//调用父类的构造函数"Student(string, number)"
this.base(name, age);
},
//重写了父类的重载函数
'print()': function(){
alert('MaleStudent: name:' + this.name + ',age:' + this.age);
},
'print(string, number)': function(name, age){
//通过this.base调用父类函数"print(string, number)"
this.base('<'+name+'>', '<' + age + '>');
},
//模糊匹配,这个函数可接受一个或多个字符串和零个或多个数字
'print(string+, number*)': function(){
var msg = [];
for(var i=0; i<arguments.length; i++){
msg.push(arguments[i]);
}
alert('print(string+, number*):' + msg.join('+'));
}
});
//创建对象时会自动判断调用的构造函数
var studentA = new com.site.Student();
studentA.print();
var studentB = new com.site.MaleStudent('王小虎', 19);
studentB.print();
studentB.print('小虎', 19);
//这里调用了模糊匹配的重载函数
studentB.print('a','b','c');
studentB.print('x','y','z', 1, 2 ,3);
var studentC = new com.site.MaleStudent();
studentC.print();
//调用静态重载函数
var student = com.site.Student.create();
student.print();
com.site.Student.search();
com.site.Student.search('某同学');
//共有的静态函数会继承到子类,所以MaleStudent也可以create
var maleStudent = com.site.MaleStudent.create('小红', 18);
maleStudent.print();
com.site.MaleStudent.search('小明');
com.site.MaleStudent.search('小明',20);
//6.匿名定义
//有些时候,我们不希望显示的指定一个类或函数的名字,只希望把它保存到变量里面,那么可以通过匿名的方式进行定义。
//1)使用lang.Class创建匿名类
var clazz = lang.Class({
//匿名类的名字统一为Anonymous,所以构造函数的名字也要是Anonymous
Anonymous: function(name){
this.name = name;
},
show: function(){
alert(this.name);
}
});
alert(clazz);
new clazz('匿名类').show();
//2)使用lang.Function创建匿名重载函数
var fn = lang.Function({
'(default)': function(){
var a = [].slice.call(arguments, 0);
alert(a);
},
'(string)': function(a){
alert('(string): ' + a);
},
'(string, number)': function(a, b){
alert('(string, number): ' + a + ':' + b);
},
'(number)': function(a){
alert('(number): ' + a);
}
});
alert(fn);
fn('message');
fn('message', 1);
fn(1);
fn(1,2,3,4,5);
//3)使用lang.Object创建支持重载函数的普通对象
var obj = lang.Object({
name: 'jim',
'write()': function(){
this.write(this.name);
},
'write(string)': function(name){
alert(name);
}
});
obj.write();
obj.write('joe');
//7.综合例子
Package("com.site").
Class('ClassA', {
print: function(){
alert(this.toString());
}
}).
Class('ClassB', {
print: function(){
alert(this.toString());
}
}).
Object({
fn1: function(){
alert(1);
},
fn2: function(){
alert(2);
},
'debug(string)': function(msg){
alert(msg);
},
'debug(string, number)': function(msg, num){
alert(num + ': ' + msg);
},
'debug(com.site.ClassA, string)': function(c, method){
alert('debug ClassA');
c[method]();
},
'debug(com.site.ClassB, string)': function(c, method){
alert('debug ClassB');
c[method]();
},
'debug(element)': function(element){
alert('element:' + element.outerHTML);
}
}).
Object('Web', {
'reload': function(){
alert('reload...');
},
'reload(function)': function(fn){
fn();
}
}).
Package('com.site.util').
Function('myfn(string)', function(name){
alert(name);
}).
Function('myfn(number)', function(num){
alert(num*num);
}).
Class('ClassA', {
ClassA: function(){
alert('ClassA!');
}
});
var div = document.createElement("div");
var span = document.createElement("span");
div.appendChild(span);
com.site.fn1();
com.site.fn2();
com.site.debug('info');
com.site.debug('info', 1);
com.site.debug(new com.site.ClassA(), 'print');
com.site.debug(new com.site.ClassB(), 'print');
com.site.debug(div);
com.site.Web.reload();
com.site.Web.reload(function(){alert('callback');});
com.site.util.myfn('Jim');
com.site.util.myfn(100);
new com.site.util.ClassA();
//8.自描述信息
/*
自描述就是类或对象在定义完成后对自身的信息的描述,常常用于实现一些特殊的功能,库中通过Type"保留字"存储类或包的自描述信息。
下面为使用方法:
*/
var value = com.site.Student;
alert('判断是否一个类:' + (value.Type && value.Type.type == 'class'));
alert('取完整类名:' + com.site.Student.Type.name);
alert('取父类完整类名:' + com.site.MaleStudent.Type.baseClass.Type.name);
alert('取短类名:' + com.site.Student.Type.shortName);
alert('取一个类的包名:' + com.site.Student.Type.Package.Type.name);
二.源码详解
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
};
})();
/***********************************
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,可以在这里免费下载,如发现什么问题,或有好的建议可以反馈给我。