lang.js 라이브러리는 기본적으로 대부분의 객체 지향 디자인 요구 사항을 충족할 수 있는 패키지 및 클래스 정의, 클래스 상속 및 믹스인(mixin), 함수 오버로딩 및 기타 기능을 제공합니다. 또한 체인 기반 정의 방법을 지원하여 라이브러리를 더욱 표준화하고 사용하기 편리하게 만듭니다. 다음은 먼저 간단한 예제를 통해 lang.js의 기본 기능을 설명한 후 lang.js의 소스 코드와 설명을 제공합니다.
1. 함수 소개
"lang"은 프레임워크의 전역 정의 역할을 하며 다음 네 가지 메서드를 포함합니다.
lang.Package(문자열 이름) //패키지를 정의하는 데 사용됩니다. 기본적으로 world)
lang.Class(string name[, object config], object classBody) //클래스를 정의하는 데 사용됩니다.
lang.Object(string name | object body) //지원하는 일반 객체를 정의하는 데 사용됩니다. 오버로드 함수
lang.Function(문자열 이름 | 객체 본문) //오버로드 함수 정의에 사용
var lang = (function(){
/***********************************
Javascript 객체지향 확장 라이브러리(lang.js v1.0)
작성자: X!ao_f
QQ: 120000512
메일: 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(){
//In 초기화 먼저 매핑 정보를 호출하고 캐시합니다
if(!method.__initialized__){
initializeMethod(method)
}
//매개변수 유형을 함수 서명에 연결합니다.
var sign; 🎜>if(arguments.length){
var list = [];
for(var i=0; i
var typename; [i];
if(인수 === 정의되지 않음 || 인수 === null){
유형 이름 = '객체'
}else if(인수 인스턴스 배열){
유형 이름 = ' array';
}else if(인수 인스턴스){
유형 이름 = '날짜';
}else{
유형 이름 = 유형 인수;
if(유형 이름 == '객체') {
if('Class' in 인수){
typename = 인수.Class.Type.name
}else if('nodeType' in 인수){
typename = 'element'; 🎜>}
}
}
list.push(typename);
}
signature = list.join(',')
}else{
signature = '';
}
//일반 캐시에 일치하는 서명이 있으면
if(method.__overloads__[signature]){
return method.__overloads__[signature]를 직접 호출합니다. (this, 인수);
}else{
//캐시에 존재하지 않는 경우 정규식을 사용해 퍼지 매칭을 시도합니다
//먼저 퍼지 매칭에 레코드가 있는지 확인합니다. 그렇다면 직접 호출하세요.
if(method.__overloadsCache__[signature]){
return method.__overloadsCache__[signature].apply(this, 인수)
}
//Loop match
for(var i=0 ; i//일치에 성공하면 매핑 관계를 퍼지 매칭 캐시에 저장하고 호출하여 반환합니다
if(method.__overloadsRegExp__[i].regexp.test( 서명)){
method.__overloadsCache__[signature] = method.__overloadsRegExp__[i].fn
return method.__overloadsRegExp__[i].fn.apply (this, 인수);
}
}
//해당 함수를 여전히 찾을 수 없으면 기본 함수가 있는지 확인
if(method.__overloads__['default']){
return method.__overloads__['default'].apply(this , 인수);
}else if(method.__overloads__['']){
return method.__overloads__[''].apply( this, 인수);
}else{
alert( '오류: ' method.Type.name '(' 서명 ')이 정의되지 않았습니다.')
}
}
};
//내장 객체
method.__context__ = context;
method.__functions__ = {};
method.toString =
//자체 설명 정보
메서드 .Type = {
이름: 이름,
메서드: 메서드,
유형: '메서드'
}
반환 메서드
}
//초기화
var generateMethod = function(method){
//기본 서명 캐시
method.__overloads__ = {};
//퍼지 일치 일반 캐시
method.__overloadsRegExp__ =
// 퍼지 일치 결과 캐시
method.__overloadsCache__ = {};
// 정의된 모든 함수 나열
for(var signed in method.__functions__){
var fn = method.__functions__[signature]; 🎜>var params = 서명.substring(signature.indexOf('(') 1, 서명.길이 - 1);
var pure = !/[* ?{]/.test(params);
/ /와일드카드가 없으면 기본 서명 캐시에 직접 저장
if(pure ){
method.__overloads__[params] = fn
}else{
//퍼지 매칭 정규 생성
var regexp = '^' params
.replace(/([w. ] )({.*?})?/g, '($1(,|$))$2')
. 교체(/./g, '\.')
.replace(/(( ()var(())/g, '$2\w $3')
.replace(/,(/g, '(') '$';
method.__overloadsRegExp__.push({ regexp: new RegExp(regexp), fn: fn })
}
}
method.__initialized__ = true; 🎜>}
//외부 정의 함수 반환
return 함수(signature, fn, comp){
//객체가 전달되면 익명 메서드를 정의한 것으로 간주합니다
(서명 유형 == '객체'){
var context = {};
var method;
for(var key in 서명){
method = createMethod.call(context, 'anonymous' 키, 서명[키]);
}
반환 방법;
}
signature = 서명.replace(/s /g, ''); '(');
var 이름 = 인덱스 > -1 ? Signature.substring(0, Signature.indexOf('(')) : 서명;
var context = this;
var 메소드 = context [name];//컨텍스트에 함수 정의가 없으므로 첫 번째 정의로 간주됩니다.
if(method === undefine){
context[name] = method = createMethodProxy(context , 이름)
}else if(!method.Type || method.Type.type!='method'){
//Context에 존재하는 함수는 Native 함수이고, 이 함수는 기본 함수 var temp = 메소드 ;
context[name] = 메소드 = createMethodProxy(컨텍스트, 이름);
method.__functions__[name '()'] = temp; /컨텍스트가 다른 경우 생성 새 오버로드 메서드는 기존 함수를 복사합니다. 이는 주로 클래스 상속 시 하위 클래스와 상위 클래스 간의 충돌 문제를 해결합니다.
//컨텍스트가 동일한 경우 초기화 표시를 직접 설정합니다. false로 설정하고 초기화
if(method.__context__ !== context){
var temp = method;
context[name] = method = createMethodProxy(context)
(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__[서명] = fn;
}
}
}else{
//마지막 이동 전략
if(fn.__functions__){
for(fn의 var 키. __functions__){
if(key in method.__functions__){
fn.__functions__[key].__overridden__ = method;
}
method.__functions__[key] = fn.__functions__[key];
}
}else{
if(method.__functions__의 서명){
fn.__overridden__ = 메서드
}
method.__functions__[signature] =
}
}
if(this.Type && this.Type.type == 'package'){
return this
}else{
return method; >};
})();
//클래스 정의 함수
var createClass = (function(){
var Slice = Array.prototype.slice;
varemptFn = 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, 유형: true} ;
//빠른 얕은 복사
function clone(a){
var fn = function(){}
fn.prototype = a
return new fn; >}
//객체 복사, 기존 항목 바꾸기(마지막 항목부터)
function replacement(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[키]
}
}else{
base[키] = self[키]
}
}
}
}
//객체 복사, 보수만 취하세요(먼저 염두에 두세요)
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 [키];
}else{
self[키] = base[키]
}
}
}else if(!(자체의 키)){
self [key] = base[key];
}
}
}
}
return function(){
//매개변수 처리
if(this.Type && this .Type.type == '패키지'){
if(arguments.length == 2){
var name = 인수[0]
var body = 인수[1]; } else{
var name = 인수[0];
var config = 인수[1]
var body = 인수[2]
}else{
if ( 인수.길이 == 1){
var name = 'Anonymous';
var body = 인수[0]
}else{
var name = 'Anonymous'; config = 인수[0];
var body = 인수[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|| 몸;
}
//상속 처리
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(mixin 인스턴스of 배열){
for(var i=0; ireplace(clazz.prototype, mixin[i])
}
}else{
replace(clazz.prototype, mixin);
}
}
//내장 함수 추가
clazz.prototype.base =
clazz; 프로토타입.self = selfCaller;
clazz.prototype.constructor = clazz;
clazz.prototype.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 ' .' 이름,
shortName: 이름,
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 = {
type: 'object',
name: 이름,
baseClass: baseClass
}
if(clazz의 이름){
clazz[name].call(clazz)
}
return clazz;
}; )();
//오버로딩을 지원하는 일반 객체를 만드는 데 사용됩니다.
var createObject = function(objects, config){
var target
if(this.Type && this.Type.type; == '패키지') {
target = this;
}else{
target = {}
}
if(typeofobjects == 'string'){
target = this[objects] = {};
objects = config;
}else if(typeofobjects == 'function'){
objects = object()
}
for( 객체의 var 키){
if(typeof 객체[key] == 'function' && (key.indexOf('(') > -1 || typeof target[key] == 'function')){
createMethod.call(대상, 키, 개체[키])
}else{
대상[키] = 개체[키]
}
}
if(this .Type && this.Type .type == 'package'){
return this;
}else{
return target
}
}//생성하는 데 사용됩니다. 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 = {
클래스: createClass,
객체: createObject,
함수: createMethod,
패키지: createPackage,
toString: customToString
}
pack.Type = {
type: 'package',
패키지: pack,
name : name.join(' .')
}
parent = parent[path[i]] = pack
}
}
부모 반환
}
} )();//패키지는 기본적으로 노출됩니다.
window.Package = createPackage;
return {
Package: createPackage,
Class: createClass,
Function: createMethod,
객체: createObject
};
})();
결론:
이 시점에서
lang.js
의 적용 및 원리는 다음과 같습니다. 이 라이브러리는 주류에 있으며 브라우저에서 테스트되었습니다.
lang.js를 사용하려면 여기에서 무료로 다운로드할 수 있습니다. 피드백을 주세요.