d. クラス メソッドを実装します
klass の基本的な設計思想は非常に明確であり、継承を模倣するよう最善を尽くしています。他の言語のメソッド。たとえば、サブクラスのコンストラクターは親クラスのコンストラクターを呼び出しますが、親クラスのメソッドを呼び出すように明示的に宣言することもできます。
この種の判断は通常のマッチングに基づいています: fnTest=/xyz/.test(function(){xyz;})?/bsuprb/:/.*/; キーワード "super"
If親クラスのメソッドを呼び出すことが明示的に宣言され、メソッドが宣言されると、内部で親クラスのメソッドを呼び出し、同じ値を現在のクラスのメソッドに返す関数にパッケージ化されます。
一方で、工法も比較的柔軟です。 initialize が明示的に宣言されている場合、これがコンストラクターになります。それ以外の場合、パラメーターが関数の場合はそれがコンストラクターとして使用され、それ以外の場合は親クラスのコンストラクターが使用されます。
/**
*Klass.js-copyright@dedfat *バージョン 1.0
*https://github.com/ded/klass
*Followoursoftwarehttp://twitter.com/dedfat:)
*MITLicense
*/
!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;
//上の super から同じ名前のメソッドを借用するように this.super を一時的に変更します
// o (fnTest.text(fn)= =true) に明示的なステートメントを指定します。同じ名前のスーパー メソッドを借用するには、
this.supr=supr[proto][k] を使用します。
//実行を借用します。戻り値を保存します
varret=fn.apply(this,arguments);
//元の this.super
this.supr=tmp
//確実に戻り値を返します。ラップ後の戻り値が元の
} と一致していること
}
// 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上記の klass では、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 が関数である場合、それは上記の _constructor によって決まります。 constructor
fn=function() {//kclass は kclass に依存しているため、実際に最終的に返されるのは fn であり、実際には新しいクラスのコンストラクターです
//1 If o が {... o のプロトタイプで、o に初期化がある場合、fn のプロトタイプに初期化がある場合、それはコンストラクター メソッドです。
//2 If oは関数です。メソッドは fn のプロトタイプに何も追加できませんが、_constructor は o をコンストラクターとして受け入れます
//3 o が {....} で、その中に初期化がない場合、これがコンストラクターですklass の呼び出しによって決定される場合、コンストラクターは明らかに noop です。非基底クラスの場合、コンストラクターは親クラスのコンストラクターです。
//o は関数ではないため、親のコンストラクターです。 class は自動的には呼び出されませんが、親クラスのコンストラクターは現在のクラスのコンストラクターとみなされます ----this すべては、この
console.log(this)> のポイントによって決まります。 if(this.initialize){
this.initialize.apply(this,arguments);
}else{
//親クラスのコンストラクターを呼び出します
//上の 3 に示すように、o は関数ではないため、親クラスのコンストラクターは呼び出されません
//基本クラスには親クラスがなく、親クラスのコンストラクターは Sub |
_constructor から呼び出されません。 .apply(this,arguments);
}
}
// プロトタイプ メソッド インターフェイスを構築します
fn.methods=function(o){
process(prototype,o,supr);
fn[proto]=prototype;
returnthis;
}
// 新しいクラスのコンストラクターを実行します
fn .methods.call(fn) ,_methods).prototype.constructor=fn;
//新しいクラスが継承できることを確認します
fn.extend=arguments.callee
//インスタンス メソッドまたは静的メソッドを追加します、statics: static メソッド、インスタンスメソッドを実装します
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!=='unknown' &&module) .exports){
module.exports=klass;
}else{
varold=context.klass;
//アンチコンフリクト
klass.noConflict=function(){
context.klass=old;
returnthis;
//フロントエンドブラウザの場合
context.klass=kclass;
}(this,'関数')
;
3. 간단한 구현도 있습니다 구현 아이디어는 매우 간단합니다. 즉, ECMAScript5 프로토타입을 사용하여 Object.create 메서드를 상속하고 이를 메서드로 캡슐화하는 것입니다. ECMAScript5 환경은 지원하지 않으므로 번역되어 성능이 저하됩니다.
functionF(){};
F.prototype=superCtor.prototype;
ctor.prototype=newF()
ctor.prototype.constructor=ctor;
마지막 매개변수가 현재 클래스의 메서드 선언이라는 점을 제외하면 다른 매개변수는 상위 클래스에서 상속되어 순환 상속이 필요하지만 여기에서의 처리는 비교적 간단하고 덮어쓰기가 포함되지 않습니다. 직접 추가할 수 있습니다.
varClass=(function(){
/* *
*함수 상속.(node.js)
*
*@paramctorsubclass'sconstructor.
*@paramsuperctorsuperclass의 생성자.
*/
varinherits=function(ctor,superCtor){
//부모 클래스를 명시적으로 지정
ctor.super_=superCtor;
//ECMAScript5 프로토타입 상속 및 역참조
if(Object.create){
ctor.prototype=Object.create(superCtor.prototype,{
생성자:{
값:ctor,
열거 가능:false,
쓰기 가능 :true,
configurable:true
}
});
}else{
//Object.create 메서드 없이 원활한 성능 저하
functionF(){}; .prototype=superCtor.prototype;
ctor.prototype=newF();
ctor.prototype.constructor=ctor;
}
}; 🎜>returnfunction(){
//마지막 매개변수는 새 클래스 메서드, 속성 및 생성자 선언입니다.
varsubClazz=arguments[arguments.length-1]||function(){}; 초기화는 생성자이고 그렇지 않으면 생성자는 빈 함수입니다.
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;
}
})()
다음 예를 참조하세요.
복사 코드
코드는 다음과 같습니다.
*/
initialize:function(name){
this.name=name
},
/**
*건축자.
*
*@paramname고양이 이름
*/
eat:function(){
alert (this. name "iseatingfish.");
}
})
/**
*먹기 기능.
*/
varBlackCat=Class(Cat,{
/**
*BlackCat 클래스의 정의.
*/
initialize:function(name,age){
//calltheconstructorofsuperclass.
BlackCat.super_.call(this,name)
this.age=age
} 🎜>/ **
*건축자.
*
*@paramname고양이 이름.
*@paramageCat'sage.
*/
eat:function(){
alert(this.name "(" this.age ")iseatingdog.")
}
});
/**
*먹기 기능.
*/
varBlackFatCat=Class(BlackCat,{
/**
*BlackFatCat 클래스의 정의입니다.
*@paramweightCat'sweight.
*/
초기화:함수(이름, age,weight ){
//calltheconstructorofsuperclass.
BlackFatCat.super_.call(this,name,age)
this.weight=weight;
/**
*건축자.
*
*@paramname고양이 이름.
*@paramageCat'sage.
*@paramweightCat의 체중입니다.
*/
eat:function(){
alert(this.name "(" this.age ")iseatingdog.Myweight:" this.weight)
}
}); >/* *
*먹기 기능.
*/
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 클래스의 소스 코드 분석 라이브러리는 여기에서 볼 수 있습니다: 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({ 초기화:function(){ alert('moooo'); } });
b. 継承の実装
varAnimal =newClass( {
initialize:function(age){
this.age=age;
}
});
varCat=newClass({
Extends:Animal, initialize: function(name,age){
this.parent(age);//callsinitalizemethodofAnimalclass
}
});ミシア'、20);
alert(myCat.name);//alerts'Micia'。
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'); );//alerts' Micia'.
5. JavaScript の理解: 構文 Nectar
まず使用例を見てください
a.
コードをコピー
this.age=age;
},
SayHello:function(){
alert("こんにちは、私は「この .name "、" this.age "年です。")
}
}); );
BillGates.SayHello() ;
継承クラス
コードをコピーします。コードは次のとおりです。
//従業員は Person を継承します
alert( this.name "$" this.salary);
}
});
varSteveJobs=New(従業員,["SteveJobs",53,1234]);
SteveJobs.ShowMeTheMoney();
以下はソース コード分析です: 明らかに、追加の New メソッドがあり、クラスと新しいクラスのインスタンスの作成は巧妙にカプセル化されています。意味のある全体を形成します!もう 1 つの違いは、すべてのクラスが関数ではなくリテラルに基づいていることです。コードは非常に短いですが、原理は豊富で賢明なので、じっくり味わうことができます。
コードをコピー
コードは次のとおりです:
//クラスを作成する関数。使用されます。クラスと継承関係を宣言します
functionClass(aBaseClass,aClassDefine){
class_.prototype=aBaseClass;
returnnewclass_()
};
// オブジェクトを作成する関数
functionNew(aClass) ,aParams){
// オブジェクトの一時的な関数シェルを作成します
functionnew_(){
this.Type=aClass;
// また、以下に基づいて各オブジェクトに Type 属性を割り当てます。これにより、オブジェクトが属するクラスにアクセスできます。
if(aClass.Create)
aClass.Create.apply(this, aParams);
//すべてのクラスのコンストラクターが Create と呼ばれることに同意します。これは DELPHI
};
new_.prototype=aClass;
returnnewnew_()
}; に似ています。解析されていない箇所が多く、不正確な箇所があるかもしれませんので、修正してください。
上記の分析を読んだ後、その情報に従って独自のカプセル化クラス ライブラリを作成することもできます。実装方法については、個人の好みによって異なります。ただし、基本的な考え方は同じプロトタイプベースの継承方法と新しい循環コピー方法です。
原文: Mu Yi http://www.cnblogs.com/pigtail/