The lang. js Library provides the definition of packages and classes, class inheritance and mixing (mixin), function overloading, and other functions, which can basically meet the needs of most object-oriented design. It also supports the chain-based definition method to make the library more standardized and convenient for use. The following uses a simple example to demonstrate the basic functions of lang. js, and then provides the source code and comments of lang. js.
I. Features
As a global definition of the framework, "lang" includes four methods:
Lang. Package (string name) // defines the Package (Global by default)
Lang. Class (string name [, object config], object classBody) // defines a Class
Lang. Object (string name | object body) // defines common objects that support overload functions.
Lang. Function (string name | object body) // defines the overloaded Function.
Copy codeThe 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 + ']';
}
// Supports definition of overloaded Methods
Var createMethod = (function (){
// Create a proxy Function
Var createMethodProxy = function (context, name ){
// When calling an overloaded function, the system first analyzes the input parameters for matching and forwarding.
Var method = function (){
// Initialize the ing information during the first call and cache the ing information
If (! Method. _ initialized __){
InitializeMethod (method );
}
// Concatenate the parameter type into a function Signature
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 a matching signature exists in the regular cache, directly call
If (method. _ overloads _ [signature]) {
Return method. _ overloads _ [signature]. apply (this, arguments );
} Else {
// If the cache does not exist, use the regular expression to perform fuzzy match.
// First, judge whether a record exists in the fuzzy match cache. If yes, call it directly.
If (method. _ overloadsCache _ [signature]) {
Return method. _ overloadsCache _ [signature]. apply (this, arguments );
}
// Loop matching
For (var I = 0; I <method. _ overloadsRegExp _. length; I ++ ){
// If the matching succeeds, the ing relationship is saved to the fuzzy match cache, called at the same time, and returned
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 the default function exists
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;
// User description
Method. Type = {
Name: name,
Method: method,
Type: 'method'
};
Return method;
}
// Initialization
Var initializeMethod = function (method ){
// Basic signature Cache
Method. _ overloads _ = {};
// Fuzzy match regular Cache
Method. _ overloadsRegExp _ = [];
// Fuzzy match result Cache
Method. _ overloadsCache _ = {};
// Example of 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 no wildcard exists, save it to the basic signature cache.
If (pure ){
Method. _ overloads _ [params] = fn;
} Else {
// Generate a fuzzy match 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 definition function
Return function (signature, fn, comp ){
// If an object is input, the anonymous method is defined.
If (typeof signature = 'object '){
Var context = {};
Var method;
For (var key in signature ){
Method = createMethod. call (context, 'anonus us' + 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];
// Function definition does not exist in the context. It is considered as the first definition.
If (method = undefined ){
Context [name] = method = createMethodProxy (context, name );
} Else if (! Method. Type | method. Type. type! = 'Method '){
// The Function in the context is a native function, which is saved to 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 a new overload method and copy existing functions. This mainly solves the conflict between subclass and parent classes in class inheritance.
// If the context is the same, set the initialization flag to false and re-initialize it when the next call is made.
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 defined function to the function list
// Preemptible Policy
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 {
// Post-entry-Based Policy
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-defined functions
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 ));
};
}
// Call the rewritten 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 );
}
}
// Call its own overload 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 copy
Function clone (){
Var fn = function (){};
Fn. prototype =;
Return new fn;
}
// Object replication, replace existing (post-entry-based)
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 function has been overloaded
If (key. indexOf (')>-1 | (base [key] & base [key]. _ functions __)){
CreateMethod. call (base, key, self [key]);
} Else {
// General Function Definition
If (key in base ){
// Record rewrite Information
Self [key]. _ overridden _ = base [key];
}
Base [key] = self [key];
}
} Else {
Base [key] = self [key];
}
}
}
}
// Object replication, only the complementary set (preemptible)
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 = 'anonus us ';
Var body = arguments [0];
} Else {
Var name = 'anonus us ';
Var config = arguments [0];
Var body = arguments [1];
}
}
// Create basic functions of the class
Var clazz = createClass (name );
// Obtain the parent class information
Var baseClass;
If (config & config. extend ){
BaseClass = config. extend;
}
// If the input body is a function, return the value
If (typeof body = 'function '){
Body = body (clazz );
}
// Process static members
If (body. Static ){
Complement (clazz, body. Static );
Delete body. Static;
Body = body. Public | body;
} Else {
Body = body. Public | body;
}
// Process inheritance
If (baseClass ){
// Copy a parent class member through a quick copy.
Clazz. prototype = clone (baseClass. prototype );
// Inherit static members
Complement (clazz, baseClass );
// Inherit class members
Complement (clazz. prototype, body );
} Else {
// Inheritance does not exist
Clazz. prototype = {};
Complement (clazz. prototype, body );
}
// Process mixing
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 );
}
}
// Add built-in functions
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 __){
// When an overload exists, add its own reference for calling the overload constructor through this. self
Constructor. _ functions _ [key]. _ self _ = constructor;
// When inheritance exists, use the constructor of the parent class as the rewritten function and configure it 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-description
// If the current context is a package, add the class to the package
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 the static Constructor
If (name in clazz ){
Clazz [name]. call (clazz );
}
// Return this for chained call
Return this;
} Else {
// Return directly if the context is not a package
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;
}
};
})();
// Creates a common object that supports heavy loads.
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 a package
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;
}
})();
// The 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, and the library has been tested in mainstream browsers,
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.