クラス
7235 ワード
本文はMVCのJavaScript Webリッチアプリケーションから整理して開発しました.オリジナル書籍の購入を歓迎します.コンストラクタは、インスタンスオブジェクトに属性と値を初期化するために使用されます.どのJavaScript関数も構造関数として使用できます.構造関数はnew演算子をプレフィックスとして使用して新しい例を作成しなければなりません.new演算子は、関数の実行コンテキストを変更しながら、return文の動作を変更します.実際には、newと構造関数を使って、伝統的にクラスの言語での使用方法を実現するのに似ています.
var Person = function(name) {
this.name = name;
};
// Person
var alice = new Person('alice');
//
assert( alice instanceof Person );
または、元のタイプ以外の任意の値を返します.例えば、新しいクラスの関数を作成するために戻ってもいいです.最初のステップは自分のクラスのアナログライブラリを作成することです.var Class=function(){
var klass=function(){
this.init.apply(this,arguments);
}
klass.prototype.inti=function(){};
return klass;
}
var Person=new Class; // new Person function
Peson.prototype.init=function(){
// Person
}
5、JavaScriptでは、クラスに関数を追加し、オブジェクトに属性を追加するのは同じPerson.find=functon(){}です.var person=Perons.find();コンストラクタにインスタンス関数を追加するには、コンストラクタのプロトタイプPerson.prototype.breeath=function(){}が必要です.var person=new Person()person.breeath()一般的によく使われるパターンはクラスのプロトタイプに別名を付けます.fn Person.fn=Person.proptype.Person.fn.run=function(){}6、クラスに直接属性を設定し、その静的なメンバーを設定するのは等価である:var Person=new Class;直接クラスに静的方法Person.find=function(*)////////を追加します.このように私達は直接それらのvar person=Person.findを呼び出すことができます.クラスのプロトタイプに設定した属性はクラスの例でも使用できます.プロトタイプに関数Person.prototype.save=function()//////を定義します.このようにして、それらのvar person=new Personを実例において呼び出すことができる.person.save();もう一つの異なる方法を採用して、クラスに属性を追加します.ここでは二つの関数extedとincludeを使いました.var class=function(){
var klass=function(){
this.init.apply(this,arguments);
};
klass.prototype.init=function(){};
// prototype
klass.fn=klass.prototype;
//
klass.fn.parent=klass;
//
klass.extend=function(obj){
var extended=obj.extended;
for(var i in obj){
klass[i]=obj[i];
}
if(extended) extended(klass);
};
//
klass.inclue=function(obj){
var inclued=obj.inclued;
for(var i in obj){
klass.fn[i]=obj[i];
}
if(inclued) inclued(klass);
};
}
var Person=new Class;
Person.extend({
find:function(id){}
exists:functions(id){}
});
var person=Person.find(1);
include()関数の動作原理も同じです.属性をクラスにコピーするのではなく、クラスの原型にコピーします.言い換えれば、ここでの属性はクラスインスタンスの属性であり、クラスの静的属性ではない.var Person=new Class;
Person.include({
save:function(){},
save:functions(id){}
})
var person=new Person;
person.save();
7、プロトタイプに基づくクラスの継承は、Aray.prototypeに属性を追加すれば、すべてのJavaScript配列はこれらの属性を持っています.コードは以下の通りですvar Animal=function(){};
Animation.prototype.breath=function(){
console.log("breath");
}
var Dog=function(){};
//
Dog.prototype=new Animal;
Dog.prototype.wag=function(){
console.log("wag')
}
var dog=new Dog();
dog.breath();
dog.wag();
「クラス」ライブラリに引き継ぎを追加して、私達がカスタマイズした「クラス」ライブラリに引き継ぎを追加します.私達はオプションの親に入ることによって、新しいクラスを作成します.var Class=function(){
var klass=funtion(){
this.init.apply(this,arguments);
};
// class
if(parent){
var subclass=function(){};
subclass.prototype=parent.prototype;
klass.prototype=new subclass();
};
kclass.prototype.inti=function(){};
//
klass.fn=klass.prototype;
kclass.fn.parent=klass;
kclass._super=kclass.__prototype__;
/* include/extend …… */
return klass;
}
var Class=function(){
var klass=funtion(){
this.init.apply(this,arguments);
};
// class
if(parent){
var subclass=function(){};
subclass.prototype=parent.prototype;
klass.prototype=new subclass();
};
kclass.prototype.inti=function(){};
//
klass.fn=klass.prototype;
kclass.fn.parent=kclass;
kclass._super=kclass.__prototype__;
/* include/extend …… */
klass.extend=function(obj){
var extended=obj.extended;
for(var i in obj){
klass[i]=obj[i];
}
if(extended) extended(klass);
};
//
klass.inclue=function(obj){
var inclued=obj.inclued;
for(var i in obj){
klass.fn[i]=obj[i];
}
if(inclued) inclued(klass);
};
return klass;
}
8、関数呼び出しはjavascriptの中で、関数とその他のものはすべて対象ですが、関数は呼び出しられます.jQueryは、そのAPIの実装において、appry()とcall()を利用してコンテキストを変更します.例えば、イベントハンドラにおいて、またはeach()を使って反復する場合.最初は理解しにくいですが、理解すれば非常に役に立つと思います.$('.clicky’).click(function(){
// ‘this’
$(this).hide();
});
$('p’).each(function(){
// ‘this’
$(this).remove();
});
元のコンテキストにアクセスするために、ローカル変数にthisの値を保存することができます.これは一般的なモードです.var clicky=function(){
wasClicked:function(){};
addListeners:function(){
var self=this;
$('.cicky').click(
fuction(){
sele.wasCliked();
};
)
}
}
clicky.addListeners();
, apply , , :
var proxy=function(func,thisObject){
return (
function (){
return func.apply(thisObject,arguments);// func
}
)
}
var clicky={
wasClicked:function{};
addListener:function(){
var self=this;
$('.clicky').click(proxy(this.wasClicked,this));
}
}
var App {
log: function(){
if (typeof console == "undefined") return;
//
var args = jQuery.makeArray(arguments);
//
args.unshift("(App)");
// console
console.log.apply(console, args);
}
};
9、クラスの役割領域を制御します.クラスとインスタンスにproxy関数を追加します.このようにして、イベントハンドラ以外で関数を処理する時と以下のコードで示したシーンでクラスの役割領域を維持できます.var Class=function(parent){
var klass=function(){
this.init.apply(this,argument)
};
klass.prototype.init=function(){};
klass.fn=klass.prototype;
klass.fn.parent=ckass;
// poxy
klass.proxy=function(func){
var self=this;
return (function(){
return func.apply(self,arguments)
})
}
//
klass.prototype=klass.proxy;
return klass;
}
proxy ,
var Button=new Class();
Button.include({
init:function(){
this.element=jQuery(element);
// click
this.element.click(this.proxy(this.click));
//this.element.click(this.click.apply(this.argument))
},
click:function(){}
});
9、プライベート関数を追加し、匿名関数を作成することによりプライベートスコープを作成します.var Person = function(){};
(function(){
var findById = function(){ /* ... */ };
Person.find = function(id){
if (typeof id == "integer")
return findById(id);
};
})();
クラスの属性を匿名関数にラッピングして、ローカル変数(findById)を作成しました.これらの局所変数は現在の作用領域にしかアクセスできません.Person変数はグローバルスコープで定義されていますので、どこでもアクセスできます.変数を定義するときは、var演算子を捨てないでください.varを捨てたらグローバル変数が作成されます.グローバル変数を定義する必要がある場合、グローバルスコープでそれを定義します.またはwindowとして定義します.(function(exports){
var foo = "bar";
//
exports.foo = foo;
})(window);
assertEqual(foo, "bar");