Home >Web Front-end >JS Tutorial >Javascript object-oriented extension library code sharing_js object-oriented

Javascript object-oriented extension library code sharing_js object-oriented

WBOY
WBOYOriginal
2016-05-16 17:54:481081browse

The lang.js library provides package and class definition, class inheritance and mixin (mixin), function overloading and other functions, which can basically meet most object-oriented design needs. It also supports a chain-based definition method, making the library more standardized and convenient to use. The following first demonstrates the basic functions of lang.js through a simple example, and then gives the source code and comments of lang.js.
1. Function introduction
"lang" serves as the global definition of the framework, which includes four methods:
lang.Package(string name) //Used to define the package (will be exposed to the world by default)
lang.Class(string name[, object config], object classBody) //Used to define classes
lang.Object(string name | object body) //Used to define ordinary objects that support overloaded functions
lang.Function(string name | object body) //Used to define overloaded functions

Copy code The code is as follows:

var lang = (function(){
/***********************************
Javascript object-oriented extension library (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 ']';
}
//Support overloaded method definition
var createMethod = (function(){
//Create a proxy function
var createMethodProxy = function (context, name){
//When an overloaded function is called, the function will first be executed to analyze the incoming parameters, match and forward
var method = function(){
//In Initialize on the first call and cache the mapping information
if(!method.__initialized__){
initializeMethod(method);
}
//Splice the parameter type into a function signature
var signature;
if(arguments.length){
var list = [];
for(var i=0; ivar 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 there is a matching signature in the regular cache, directly call
if(method.__overloads__[signature]){
return method.__overloads__[signature]. apply(this, arguments);
}else{
//When it does not exist in the cache, try to use regular expressions for fuzzy matching
//First determine whether there is a record in the fuzzy matching cache, and if so, call it directly
if(method.__overloadsCache__[signature]){
return method.__overloadsCache__[signature].apply(this, arguments);
}
//Loop matching
for(var i=0 ; i//If the match is successful, store the mapping relationship in the fuzzy matching cache, and call and return
if(method.__overloadsRegExp__[i].regexp.test( signature)){
method.__overloadsCache__[signature] = method.__overloadsRegExp__[i].fn;
return method.__overloadsRegExp__[i].fn.apply(this, arguments);
}
}
//If the corresponding function still cannot be found, determine whether there is a default function
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.');
}
}
};
//Built-in object
method.__context__ = context;
method.__functions__ = {};
method.toString = customToString;
//Self-describing information
method.Type = {
name: name,
Method: method,
type: 'method'
};
return method;
}
//Initialization
var initializeMethod = function(method){
//Basic signature cache
method.__overloads__ = {};
//Fuzzy matching regular cache
method.__overloadsRegExp__ = [];
//Fuzzy matching result cache
method.__overloadsCache__ = {};
// List all defined functions
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 there is no wildcard, save it directly to the basic signature cache
if(pure ){
method.__overloads__[params] = fn;
}else{
//Generate fuzzy matching regular
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 the external defined function
return function(signature, fn, comp){
//If an object is passed in, it is regarded as defining an anonymous method
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];
//There is no function definition in the context, it is regarded as the first definition
if(method === undefined){
context[name] = method = createMethodProxy(context, name);
}else if(!method.Type || method.Type.type!='method'){
//The function existing in the context is a native function, and this function is stored in the list as the default function
var temp = method ;
context[name] = method = createMethodProxy(context, name);
method.__functions__[name '()'] = temp;
}else{
//If the context is different, create The new overload method copies the existing function. This mainly solves the problem of conflict between subclasses and parent classes in class inheritance
//If the context is the same, directly set the initialization mark to false and wait for the next call. Initialization
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;
}
}
// Add the function defined this time to the function list
//Preconceived strategy
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{
//Last move strategy
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;
}
};
})();
//Class definition function
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));
};
}
//Used to call the overridden function
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);
}
}
//For calling itself Overloaded constructor
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} ;
//Fast shallow copy
function clone(a){
var fn = function(){};
fn.prototype = a;
return new fn;
}
//Object copy, replace existing (last entry first)
function replace(base, self){
for(var key in self){
if(!(key in filter) ){
if(typeof self[key] == 'function'){
//If the subclass function contains an overloaded signature or the parent class function has been overloaded
if(key.indexOf('( ') > -1 || (base[key] && base[key].__functions__)){
createMethod.call(base, key, self[key]);
}else{
/ /Regular function definition
if(key in base){
//Record rewrite information
self[key].__overridden__ = base[key];
}
base[key] = self[key];
}
}else{
base[key] = self[key];
}
}
}
}
//Object Copy, only take the complement (first in mind)
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){
//Record rewrite information
self[key].__overridden__ = base [key];
}else{
self[key] = base[key];
}
}
}else if(!(key in self)){
self [key] = base[key];
}
}
}
}
return function(){
//Processing parameters
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];
}
}
//Create the basic function of the class
var clazz = createClass(name);
/ /Get parent class information
var baseClass;
if(config && config.extend){
baseClass = config.extend;
}
//If the incoming body is a function, get Its return value
if(typeof body == 'function'){
body = body(clazz);
}
//Processing static members
if(body.Static){
complement(clazz, body.Static);
delete body.Static;
body = body.Public||body;
}else{
body = body.Public||body;
}
//Handle inheritance
if(baseClass){
//Copy parent class members through fast shallow copy
clazz.prototype = clone(baseClass.prototype);
//Inherit static members
complement(clazz, baseClass);
//Inherited class members
complement(clazz.prototype, body);
}else{
//There is no inheritance
clazz.prototype = {};
complement(clazz.prototype, body);
}
//Processing mixing
if(config && config.mixin){
var mixin = config.mixin;
if(mixin instanceof Array){
for(var i=0; ireplace(clazz.prototype, mixin[i]);
}
}else{
replace(clazz.prototype, mixin);
}
}
//Add built-in function
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__){
//Exists When overloading, add a self reference to call the overloaded constructor through this.self
constructor.__functions__[key].__self__ = constructor;
//When inheritance exists, use the constructor of the parent class as the object Rewritten function, configured to the constructor of the current class
//Used to call the parent class constructor through 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;
}
//Type self-describing information
//If the current context is a package, add the class to the package in
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
}
//Add the class to the package
this[name] = clazz;
//Call static construction Function
if(name in clazz){
clazz[name].call(clazz);
}
//Return this for chain calls
return this;
} else{
//If the context is not a package, return directly
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;
}
};
})();
//Used to create ordinary objects that support overloading
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;
}
};
//Used to create package
var createPackage = (function(){
var root = this;
return function(package){
var name = [];
var path = package.split('.');
var parent = root;
for(var i=0; iname.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 is exposed by default
window.Package = createPackage;
return {
Package: createPackage,
Class: createClass,
Function: createMethod,
Object: createObject
};
})();

Conclusion:
At this point, the application and principles of lang.js have been introduced. This library is in the mainstream It has been tested in the browser.
If you want to use lang.js, you can download it for free here. If you find any problems or have good suggestions, you can give me feedback.
Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn