/**
*Klass.js-copyright@dedfat
*version1.0
*https://github.com/ded/klass
*Followoursoftwarehttp://twitter.com/dedfat:)
*MIT라이센스
*/
!function(context,f){
//fnTest는 상위 상위 클래스 메서드 호출 방법을 알아내는 것이 가능한지 확인하는 데 사용됩니다. 정규식을 통해
varfnTest=/xyz/.test(function(){xyz;})?/bsuprb/:/.*/,
noop=function(){},
proto='prototype ',
isFn =function(o){
returntypeofo===f;
}
//기본 클래스
functionklass(o){
returnextend.call(typeofo= =f?o:noop ,o,1)
}
//동일한 이름의 슈퍼 메소드를 차용하는 함수로 래핑
functionwrap(k,fn,supr){
returnfunction(){
//원본 this.super 캐시
vartmp=this.supr;
//this.super를 임시로 변경하여 super 위의 동일한 이름의 메소드를 차용합니다
// o에 명시적 문 제공(fnTest.text(fn)= =true) 동일한 이름의 슈퍼 메서드를 빌리려면
this.supr=supr[proto][k]
//Borrow 실행을 사용합니다. 반환 값을 저장합니다
varret=fn.apply(this,arguments);
//원래 this.super를 복원합니다.
this.supr=tmp>//반환 값을 반환하여 래핑 후 반환 값이 원래
returnret
}
}
//o와 super에 동일한 이름의 메서드가 있고 o가 명시적으로 다음 메서드를 차용한다고 선언한 경우 super에서 같은 이름의 메서드를 사용하기 위해 실행되도록 함수에 래핑합니다
//super에서 같은 이름의 메서드를 빌리라는 명시적인 선언이 없거나 o의 고유한 메서드이거나 메소드가 아니면 그냥
functionprocess(what,o,supr){
for(varkino){
을 사용하세요.//상속되지 않는 메소드라면 메소드 주석 규칙에 따라 실행하세요. 마지막으로 what
if(o.hasOwnProperty(k)){
what[k]=typeofo[k]==f
&&typeofsupr[proto][k]==f
&&fnTest에 넣습니다. test(o[k])
?wrap(k,o[k],supr):o[k];
}
}
}
//상속된 메서드 구현, fromSub 위의 클래스에서 fromSub는 1이며, 이는 생성자가
functionextend(o, fromSub){
//noop를 실행하는 데 super를 사용하지 않음을 나타냅니다. 미디어 클래스는 프로토타입 상속의 역참조를 구현합니다
noop[proto]=this[proto];
varsupr=this,
prototype=newnoop(),//프로토타입 상속을 위한 인스턴스 객체 생성, 역참조
isFunction=typeofo==f,
_constructor=isFunction?o:this,//o가 생성 메서드인 경우 이를 사용하고, 그렇지 않으면 생성자를 결정합니다.
_methods=isFunction?{}:o, //If o는 {...}이며 fn 프로토타입에 넣으려면 메서드를 사용해야 합니다. 거기에 초기화가 있으면 생성자입니다. o가 함수인 경우 o는 a입니다. constructor
fn=function() {//kclass는 kclass에 의존하기 때문에 결국 실제로 반환되는 것은 fn입니다. 이는 실제로 새 클래스의 생성자입니다.
//1 o가 {... }, 메소드에 의해 직접 필터링되어 fn에 추가됩니다. o의 프로토타입에서 o에 초기화가 있으면 fn의 프로토타입에 초기화가 있으면 생성자 메소드입니다
//2 If o 는 함수이고 메서드는 fn의 프로토타입에 아무것도 추가할 수 없지만 _constructor는 o를 생성자로 허용합니다
//3 o가 {....}이고 초기화가 없으면 이것이 생성자입니다. . klass의 호출에 의해 결정되는 경우 생성자는 분명히 noop입니다. 기본이 아닌 클래스에서 생성자는 상위 클래스의 생성자입니다.
//o는 함수가 아니므로 상위 클래스의 생성자입니다. 클래스는 자동으로 호출되지 않지만 상위 클래스의 생성자는 현재 클래스의 생성자로 간주됩니다.---this 모두 this
console.log(this); if(this.initialize){
this.initialize.apply(this,arguments);
}else{
//상위 클래스 생성자 호출
//위의 3과 같이 o는 함수가 아니며 부모 클래스 생성자가 호출되지 않습니다
//기본 클래스에 부모 클래스가 없으며 부모 클래스 생성자가 호출되지 않습니다
Sub | .apply(this,arguments);
}
};
//프로토타입 메서드 인터페이스 구성
fn.methods=function(o){
process(prototype,o,supr);
fn[proto]=prototype;
returnthis;
}
//새 클래스의 프로토타입을 실행하고 새 클래스의 생성자를 확인합니다.
fn ,_methods).prototype.constructor=fn;
//새 클래스가 상속될 수 있는지 확인
fn.extend=arguments.callee;
//인스턴스 메서드 또는 정적 메서드 추가, statics: 정적 메서드, 인스턴스 메소드 구현
fn[proto].implement=fn.statics=function(o,optFn){
//o가 객체 객체임을 보장합니다. o가 문자열이면 메소드를 추가할 때입니다. , o가 객체라면 일괄적으로 추가된다는 의미입니다
//o에서 복사해야 하므로
o=typeofo=='string'?(function(){
varobj= { };
obj[o]=optFn;
returnobj;
}()):o
//인스턴스 메소드 또는 정적 메소드 추가, 정적 메소드 구현
process(this,o,supr);
returnthis;
}
//백엔드 사용, nodejs
if(typeofmodule!=='undefine' &&module .exports){
module.exports=klass;
}else{
varold=context.klass;
//충돌 방지
klass.noConflect=function(){
context.klass=old;
returnthis;
//프론트엔드 브라우저의 경우
//window.kclass=kclass;
context.klass=klass;
}(이것,'함수')
三、还有一种简单实现 实现思路很简单,就是利用ECMAScript5原型式继承Object.create方法,封装成一个方法,如果不支持ECMAScript5的环境,就平移退化到
functionF(){};
F.prototype=superCtor.prototype;
ctor.prototype=newF();
ctor.prototype.constructor=ctor;
同样的,除最后一个参数是当前类的方法声明,其它参数均做为继承父类,需要循环继承,但当这里处理的相对比较简单,没涉及到覆盖。你可以自己动手添加。
varClass=(function(){
/**
*Inheritsfunction.(node.js)
*
*@paramctor子类的构造函数。
*@paramsuperctorsuperclass 的构造函数。
*/
varinherits=function(ctor,superCtor){
//显式的指定父类
ctor.super_=superCtor;
//ECMAScript5原型式继承并解除引用
if(Object.create){
ctor.prototype=Object.create(superCtor.prototype,{
constructor:{
value:ctor,
enumerable:false,
writable:true,
configurable:true
}
});
}else{
//无Object.create方法的平稳退化
functionF(){};
F.prototype=superCtor.prototype;
ctor.prototype=newF();
ctor.prototype.constructor=ctor;
}
};
/**
*类函数。
*/
returnfunction(){
//最后一个参数是新类方法、属性和构造函数声明
varsubClazz=arguments[arguments.length-1]||function(){};
//initialize是构造函数,否构造函数就是一个空函数
varfn=subClazz.initialize==null?function(){}:subClazz.initialize;
//继承除最一个参数以的类,多继承,也可以用作扩展方法
for(varindex=0;index
inherits(fn,arguments[index]);
}
//实现新类的方法
for(varpropinsubClazz){
if(prop=="initialize"){
continue;
}
fn.prototype[prop]=subClazz[prop];
}
returnfn;
}
})();
看下面实例:
/**
*Cat类的定义。
*/
varCat=Class({
/**
*构造函数。
*
*@paramname猫的名字
*/
initialize:function(name){
this.name=name;
},
/**
*吃功能。
*/
eat:function(){
alert(this.name "iseatingfish.");
}
});
/**
*BlackCat类的定义。
*/
varBlackCat=Class(Cat,{
/**
*构造函数。
*
*@paramnameCat 的名字。
*@paramageCat'sage。
*/
initialize:function(name,age){
//calltheconstructorofsuperclass.
BlackCat.super_.call(this,name);
this.age=age;
},
/**
*吃功能。
*/
eat:function(){
alert(this.name "(" this.age ")iseatingdog.");
}
});
/**
*BlackFatCat类的定义。
*/
varBlackFatCat=Class(BlackCat,{
/**
*构造函数。
*
*@paramnameCat 的名字。
*@paramageCat'sage。
*@paramweight猫的体重。
*@paramweightCat'sweight.
*/
initialize:function(name,age,weight){
//calltheconstructorofsuperclass.
BlackFatCat.super_.call(this,name,age);
this.weight=weight;
},
/**
*吃功能。
*/
eat:function(){
alert(this.name "(" this.age ")iseatingdog.Myweight:" this.weight);
}
});
/**
*DogClass 的定义。
*/
varDog=Class({});
varcat=newBlackFatCat("John",24,"100kg");
cat.eat();
//true
alert(catinstanceofCat);
//true
alert(catinstanceofBlackCat);
//true
alert(catinstanceofBlackFatCat);
//true
alert(cat.constructor===BlackFatCat);
//false
alert(catinstanceofDog);
四、mootools类库的Class
源码解析可以看这里:http://www.cnblogs.com/hmking/archive/2011/09/30/2196504.html
看具体用法:
a、新建一个类
代码如下:
varCat=newClass({
initialize:function(name){
this.name=name;
}
});
varmyCat=newCat('Micia');
alert(myCat.name);//alerts'Micia'
varCow=newClass({
initialize:function(){
alert('moooo');
}
});
b. 상속 구현
varAnimal =newClass( {
initialize:function(age){
this.age=age;
}
})
varCat=newClass({
확장:동물,
initialize: function(name,age){
this.parent(age);//callsinitalizemethodofAnimalclass
this.name=name;
}
})
varmyCat=newCat(' Micia', 20);
alert(myCat.name);//alerts'Micia'.
alert(myCat.age);//alerts20
c. 확장 클래스
varAnimal=newClass({
initialize:function(age ){
this.age=age;
}
})
varCat=newClass({
Implements:Animal,
setName:function(name) ){
this .name=name
}
})
varmyAnimal=newCat(20)
myAnimal.setName('Micia')
alert(myAnimal.name) );//alerts' Micia'
5. JavaScript 이해: Nectar
사용 예를 먼저 살펴보세요a.
varPerson=Class( object,{
Create:function( name,age){
this.name=name;
this.age=age
},
SayHello:function(){
Alert("안녕하세요, 저는" .name "," this.age "yearsold.")
}
})
varBillGates=New(Person,["BillGates",53] );
BillGates.SayHello() ;
b.상속 클래스
varEmployee=Class(Person,{
Create:function(name,age,salary){
Person.Create .call(this,name,age);
//기본 클래스의 생성자 호출
this.salary=salary
},
ShowMeTheMoney:function(){
alert( this.name "$" this.salary);
}
})
varSteveJobs=New(Employee,["SteveJobs",53,1234])
SteveJobs.SayHello();
SteveJobs.ShowMeTheMoney();
다음은 소스 코드 분석입니다. 분명히 추가 New 메서드가 있으며 클래스 생성과 새 클래스의 인스턴스가 교묘하게 캡슐화됩니다. 의미있는 전체를 형성! 또 다른 차이점은 모든 클래스가 함수가 아닌 리터럴을 기반으로 한다는 것입니다. 코드는 매우 짧지만 원리는 풍부하고 기발하기 때문에 꼼꼼히 음미해볼 수 있습니다!
functionClass(aBaseClass,aClassDefine){
//클래스의 임시 함수 셸 만들기
functionclass_(){
this.Type=aBaseClass
/ /각 클래스에 상속된 클래스를 참조하는 규칙 A Type 속성을 제공합니다.
for(varmemberinaClassDefine)
this[member]=aClassDefine[member]
//클래스의 모든 정의를 현재 생성된 클래스에 복사합니다. class
}; class_.prototype=aBaseClass;
returnnewclass_()
};
//모든 클래스의 객체 생성에 사용되는 함수
functionNew(aClass ,aParams){
//객체에 대한 임시 함수 셸을 생성합니다
functionnew_(){
this.Type=aClass;
//또한 다음을 기반으로 각 객체에 Type 속성을 할당합니다. 객체가 속한 클래스에 액세스할 수 있습니다.
if(aClass.Create)
aClass.Create.apply(this, aParams)
//모든 클래스의 생성자가 Create라고 하는 데 동의합니다. , DELPHI와 유사합니다
};
returnnewnew_()
};
분석되지 않은 곳이 많아 부정확한 부분이 있을 수 있으니 정정해 주시기 바랍니다.
위 분석을 읽은 후 정보에 따라 자신만의 캡슐화 클래스 라이브러리를 작성할 수도 있습니다. 구현 방법은 개인 취향에 따라 다릅니다. 하지만 기본 아이디어는 프로토타입 기반 상속 방식과 동일하며 새로운 순환 복사 방식이다.
원문 출처: Mu Yi http://www.cnblogs.com/pigtail/