lang.js ライブラリは、パッケージとクラスの定義、クラスの継承とミックスイン (ミックスイン)、関数のオーバーロード、およびその他の機能を提供しており、基本的にほとんどのオブジェクト指向設計のニーズを満たすことができます。また、チェーンベースの定義方法もサポートしているため、ライブラリがより標準化され、使いやすくなります。以下では、まず簡単な例を通じて lang.js の基本的な機能を示し、次に lang.js のソース コードとコメントを示します。
1. 関数の紹介
「lang」はフレームワークのグローバル定義として機能し、次の 4 つのメソッドが含まれます。
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)
投稿者: X!ao_f
QQ: 120000512
メール: xiao_f.mail#163.com
******************** ***************/
varcustomToString = function(){
return '[' this.Type.type ' ' this .Type.name ']';
}
//オーバーロードされたメソッド定義をサポートします
var createMethod = (function(){
//プロキシ関数を作成します
var createMethodProxy = function (context , name){
//オーバーロードされた関数が呼び出されると、関数はまず受信パラメータを分析し、一致および転送するために実行されます。
var method = function(){
//In Initialize最初にマッピング情報を呼び出してキャッシュします。
if(!method.__initialized__){
initializeMethod(method)
}
// パラメーターの型を関数シグネチャに結合します
var シグネチャ
if(arguments.length){
var list = [];
for(var i=0; i
var typename; [i];
if(引数 === 未定義 || 引数 === null){
タイプ名 = 'オブジェクト';
}else if(配列の引数インスタンス){
タイプ名 = '配列';
}else if(日付の引数インスタンス){
タイプ名 = '日付';
}else{
タイプ名 == 'オブジェクト') {
if('クラス' 引数){
タイプ名 = 引数.Class.Type.name;
}else if('ノードタイプ' 引数){
タイプ名 = '要素 '; 🎜>}
}
}
list.push(typename);
}
signature = list.join(',');
signature = '';
}
// 通常のキャッシュに一致する署名がある場合は、
if(method.__overloads__[signature]){
return method.__overloads__[signature] を直接呼び出します。 (this, argument);
}else{
//キャッシュに存在しない場合は、あいまい一致に正規表現を使用してみてください
//まずあいまい一致にレコードがあるかどうかを判断しますキャッシュしている場合は、それを直接呼び出します
if(method.__overloadsCache__[signature]){
return method.__overloadsCache__[signature].apply(this, argument);
//ループmatching
for(var i=0 ; i//一致が成功した場合、マッピング関係をあいまい一致キャッシュに保存し、
を呼び出して返します。 if(method.__overloadsRegExp__[i].regexp.test(signature)){
method.__overloadsCache__[signature] = method.__overloadsRegExp__[i].fn
return method.__overloadsRegExp__[i].fn.apply; (this, argument);
}
}
// 対応する関数がまだ見つからない場合は、デフォルト関数があるかどうかを判断します
if(method.__overloads__['default']){
return method.__overloads__['default'].apply(this , argument);
}else if(method.__overloads__['']){
return method.__overloads__[''].apply( this, 引数);
}else{
alert( 'エラー: ' メソッド.Type.name '(' 署名 ') が定義されていません。');
}
}
};
//組み込みオブジェクト
method.__context__ = context;
method.__functions__ = {};
method.toString = customToString
//自己記述型情報
メソッド; .Type = {
name: 名前,
メソッド: メソッド,
タイプ: 'メソッド'
}
戻りメソッド;
//初期化
; varInitializeMethod = function(method){
//基本署名キャッシュ
method.__overloads__ = {};
//あいまい一致通常キャッシュ
method.__overloadsRegExp__ = [];あいまい一致結果のキャッシュ
method.__overloadsCache__ = {};
// 定義されているすべての関数をリストします
for(var signal 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, '(') '$';
メソッド.__overloadsRegExp__.push({ regexp: new RegExp(regexp), fn: fn });
}
}
メソッド.__initialized__ = true; 🎜>}
//外部定義関数を返します
return function(signature, fn, comp){
//オブジェクトが渡された場合、匿名メソッドを定義しているとみなされます
if (署名の種類 == 'オブジェクト'){
var context = {};
for(署名の var キー){
method = createMethod.call(context, 'anonymous'キー, 署名[キー]);
}
戻りメソッド;
署名 = 署名.replace(/s /g, '');
var インデックス = 署名.indexOf( '(');
var 名 = インデックス > -1 ? 署名.substring(0, 署名.indexOf('(')) : 署名;
var context = this;
var メソッド = context [name];
//コンテキスト内に関数定義がありません、最初の定義とみなされます
if(method === unknown){
context[name] = method = createMethodProxy(context 、名前);
}else if(!method.Type || method.Type.type!='method'){
//コンテキスト内に存在する関数はネイティブ関数であり、この関数はデフォルト関数としてリストに格納されます
var temp = メソッド ;
context[name] = method = createMethodProxy(context, name);
method.__functions__[name '()'] = temp; /コンテキストが異なる場合は、新しいオーバーロード メソッドが既存の関数をコピーします。これにより、主にクラス継承におけるサブクラスと親クラス間の競合の問題が解決されます。
//コンテキストが同じ場合は、初期化マークを直接設定します。 false を返し、次の呼び出しを待ちます。 (var サインイン 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(method.__functions__ の署名){
method.__functions__[signature].__overridden__ =
}else{
メソッド; .__functions__[signature] = fn;
}
}
}else{
//最後の手戦略
if(fn.__functions__){
for(fn の var key. __functions__){
if(key in method.__functions__){
fn.__functions__[key].__overridden__ = メソッド;
}
method.__functions__[key] = fn.__functions__[key];
}
}else{
if(method.__functions__ の署名){
fn.__overridden__ = メソッド;
}
method.__functions__[署名] =
}
}
if(this.Type && this.Type.type == 'package'){
return this;
}else{
return メソッド; >};
})();
//クラス定義 function
var createClass = (function(){
var slide = Array.prototype.slice;
var emptyFn = function( ){};
var createClass = function(name){
return function(){
this[name].apply(this, slide.call(arguments, 0));
}
//オーバーライドされた関数の呼び出しに使用されます。
varbaseCaller = function(){
if(arguments.length){
var args = slide.call(arguments, 0);
returnbaseCaller.caller.__overridden__.apply(this, args);
}else{
returnbaseCaller.caller.__overridden__.call(this);
/ /自身を呼び出すためのオーバーロードされたコンストラクター
var selfCaller = function(){
if(arguments.length){
var args = slide.call(arguments, 0);
return selfCaller.caller.__self__ .apply (this, args);
}else{
return selfCaller.caller.__self__.call(this)
}
}
var filter = {prototype:true, タイプ: true} ;
//高速シャローコピー
function clone(a){
var fn = function(){};
fn.prototype = a; >}
//オブジェクトのコピー、既存の置換 (最後のエントリが最初)
function replace(base, self){
for(var key in self){
if(!(key in filter) ){
if(typeof self[key] == 'function'){
//サブクラス関数にオーバーロードされたシグネチャが含まれているか、親クラス関数がオーバーロードされている場合
if(key.indexOf(' ( ') > -1 || (ベース[キー] && ベース[キー].__functions__)){
createMethod.call(ベース, キー, self[キー]); / /通常の関数定義
if(key in base){
//レコード書き換え情報
self[key].__overridden__ =
}
base[key] = self[key];
}
}else{
base[key] = self[key]
}
}
}
;コピーして、補数のみを取得します(最初に念頭に置きます)
functioncomplement(self,base){
for(var key in base){
if(!(key in filter)){
if (typeofbase[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__ =ベース [キー];
自分[キー] = ベース[キー]
}
}else if(!(自分のキー)){
self [key] = Base[key];
}
}
}
return function(){
//パラメータの処理
if(this.Type && this .Type.type == 'package'){
if(arguments.length == 2){
var name = argument[0]
var body = argument[1]; } else{
var 名 = 引数[0];
var config = 引数[2];
}
}else{
if (arguments.length == 1){
var name = 'Anonymous';
var body = argument[0];
var name = 'Anonymous'; config = argument[0];
var body = argument[1];
}
}
//クラスの基本関数を作成します
var clazz = createClass(name); 🎜>/ /親クラス情報を取得します
varbaseClass;
if(config && config.extend){
baseClass = config.extend;
//受信した本文が関数、戻り値を取得
if(typeof body == 'function'){
body = body(clazz);
}
//静的メンバーの処理
if(body.Static ){
complement(clazz, body.Static);
body.Static を削除します;
body = body.Public||body;
body = body.Public||ボディ;
}
//継承を処理します
if(baseClass){
//高速シャローコピーを通じて親クラスのメンバーをコピーします
clazz.prototype = clone(baseClass.prototype)
//静的メンバーを継承します
complement(clazz,baseClass);
//継承されたクラスメンバー
complement(clazz.prototype, body);
}else{
//継承はありません
clazz。プロトタイプ = {};
complement(clazz.prototype, body);
}
//ミキシング処理
if(config && config.mixin){
var mixin = config.mixin;
if(mixininstanceofArray){
for(var i=0; ireplace(clazz.prototype, mixin[i]); > }else{
replace(clazz.prototype, mixin);
}
}
// 組み込み関数
clazz.prototype.base = BaseCaller を追加します。プロトタイプ.self = selfCaller;
clazz.prototype.toString = カスタムToString;
clazz.prototype.Class = clazz; >if( clazz.prototype[名前]){
var コンストラクター = clazz.prototype[名前];
if(constructor.__functions__){
for(constructor.__functions__ の var キー){
//存在します オーバーロードする場合、this.self を通じてオーバーロードされたコンストラクターを呼び出すための自己参照を追加します
constructor.__functions__[key].__self__ = constructionor
//継承が存在する場合は、親クラスのコンストラクターを次のように使用します。現在のクラスのコンストラクターに設定されたオブジェクトの書き換えられた関数
//ベースを介して親クラスのコンストラクターを呼び出すために使用されます
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);
}
//チェーン呼び出しの場合はこれを返します
return this; 🎜>} else{
//コンテキストがパッケージではない場合、直接戻ります
clazz.Type = {
type:'class',
name: name,
shortName: name ,
クラス: clazz ,
baseClass:baseClass
}
clazz.prototype.Type = {
タイプ: 'object',
name: 名前,
baseClass:baseClass
}
if(clazz の名前){
clazz[name].call(clazz);
return clazz; )();
//オーバーロードをサポートする通常のオブジェクトを作成するために使用されます
var createObject = function(objects, config){
if(this.Type && this.Type.type; == 'パッケージ') {
ターゲット = this;
}else{
ターゲット = {};
if(オブジェクトの種類 == '文字列'){
ターゲット= this[オブジェクト] = {};
オブジェクト = config;
}else if(オブジェクトの種類 == '関数'){
オブジェクト = オブジェクト();
for(オブジェクトの var キー){
if(オブジェクトのタイプ[キー] == '関数' && (key.indexOf('(') > -1 || ターゲットのタイプ[キー] == '関数')){
createMethod.call (ターゲット, キー, オブジェクト[キー]);
}else{
ターゲット[キー] = オブジェクト[キー]
}
}
if(this .Type && this.Type == 'package'){
return this>}else{
return target;
}; package
var createPackage = (function(){
var root = this;
return function(package){
var name = [];
var path = package.split('. ');
varparent = root;
for(var i=0; iname.push(path[i]); path[i]]) {
parent =parent[path[i]];
}else{
var Pack = {
クラス: createClass,
オブジェクト: createObject,
関数: createMethod、
パッケージ: createPackage、
toString:customToString
};
pack.Type = {
タイプ: 'パッケージ'、
パッケージ: パック、
名: name.join(' .')
}
parent = 親[パス[i]] = パック;
}
}
親を返す
}
} )();
//パッケージはデフォルトで公開されます
window.Package = createPackage;
return {
パッケージ: createPackage,
クラス: createClass,
関数: createMethod,
オブジェクト: createObject
};
})();
結論:
この時点で、
lang.js
の応用と原則このライブラリはブラウザでテストされています。
lang.js を使用したい場合は、ここから無料でダウンロードできます。フィードバックをください。