javascript prototype分析
我說不盡然,意思是說理解Prototype的一般用法很簡單。但是真正能做到融會貫通理解Prototype確實是件很難的事情。
今天我就從Prototype的基本開始講。上文中我講了原型模式。其實在Javascript中原型也是這個意思。 Javascript中對象的原型屬性的解釋是:返回對象類型原型的引用。這是一個暈人的解釋。其實就是指定了一個需要復(fù)制的對象。
文字再多也不如代碼,上代碼,說最簡單的,任何類都繼承自O(shè)bject類:
function A()
{
//todo something
}
A.prototype=new Object();
其實這樣就相當(dāng)于Object對象是A的一個原型,這樣就相當(dāng)于了把Object對象的屬性和方法復(fù)制到了A上,和原型模式的精髓一樣吧!
好,大概了解了prototype的基本用法,我們來看看原型究竟有什么用處。
最簡單的用法,動態(tài)擴(kuò)展類的方法和屬性。
de>function People()
{
this.Jump=function(){
alert("I can jump");
}
}
現(xiàn)在要擴(kuò)充方法:
People.prototype.Run=function(){
alert("I can run,too");
}
好,測試下:
var p=new People();
p.Jump();
p.Run();
cript玩轉(zhuǎn)Prototype - Gabriel - Software Engineer" height=153 alt="Javas
cript玩轉(zhuǎn)Prototype - Gabriel - Software Engineer" height=138 alt="Javas
接下來,順帶講一下Javascript的方法種類。我個人將Javascript的方法分為三種:
<1>類方法
<2>對象方法
<3>原型方法
先看代碼,后講區(qū)別:
function People(name)
{
this.name=name;
//對象方法
this.Introduce=function(){
alert("My name is "+this.name);
}
}
//類方法
People.Run=function(){
alert("I can run");
}
//原型方法
People.prototype.IntroduceChinese=function(){
alert(" 我的名字是"+this.name);
}
測試下:
var p1=new People("Windking");
p1.Introduce();
People.Run();
p1.IntroduceChinese();
cript玩轉(zhuǎn)Prototype - Gabriel - Software Engineer" height=124 alt="Javas
cript玩轉(zhuǎn)Prototype - Gabriel - Software Engineer" height=140 alt="Javas
cript玩轉(zhuǎn)Prototype - Gabriel - Software Engineer" height=136 alt="Javas
總結(jié)下:
名稱
位置
格式
類方法
類外
類名.方法名
對象方法
類內(nèi)
this.方法名
原型方法
類外
類名.prototype.方法名
我們用C#來做類別來講解這三個方法:
類方法其實就是我們講的靜態(tài)方法:
如public static void Run(){}
而對象方法其實就是實例方法。
public void Introduce(){}
而原型方法有所不同,由于C#中不允許動態(tài)為對象增加方法,因此在C#中并不存在原型方法。原型方法處于C#的靜態(tài)方法與實例方法之間,通過對象調(diào)用,但是存儲的內(nèi)存形式卻類似于靜態(tài)方法,也就是所有實例對象共享同一副本。
(ps:盡量將方法定義為原型方法,原型方法避免了每次調(diào)用構(gòu)造函數(shù)時對屬性或方法的構(gòu)造,因此比較節(jié)省空間和時間)
p1.IntroduceChinese();創(chuàng)建對象。
還記得我在上一篇文章里講的淺復(fù)制么?為什么大家都喜歡批量生產(chǎn)?效率是最主要因素。淺復(fù)制也一樣,我們?yōu)槭裁匆獪\復(fù)制,因為效率高。作為原型模式的 Javascript應(yīng)用,prototype也承擔(dān)著這樣的重任。用prototype來創(chuàng)建對象,要比其他方式快得多。
看代碼例子:
function People(name,age)
{
this.name=name;
this.age=age;
}
var p1=new People("Xuan",22);
var girls=[ ];
var GirlPrototype=function(){};
GirlPrototype.prototype=p1;
for(var i=0;i<100000;i++)
{
girls[i]=new GirlPrototype();
}
玩轉(zhuǎn)繼承:
Prototype最大的應(yīng)用其實還是在于玩轉(zhuǎn)繼承,這個在此不討論,請參加我的另一篇文章:《Javascript玩轉(zhuǎn)繼承(二)》。
好,基本的應(yīng)用說完,下面我來說一下prototype的天使和魔鬼兩面。
說prototype是天使,是因為以上的幾點應(yīng)用,讓Javascript增加了很大的靈活性,尤其原型繼承,更是Javascript最多的繼承方式。
說他是魔鬼,則是因為下面幾方面:
原型繼承的缺陷。請參見《Javascript玩轉(zhuǎn)繼承(二)》。
原型其實相當(dāng)于原型模式中的淺復(fù)制,因此也會造成牽一發(fā)而動全身的效果。
過于靈活。為什么過于靈活呢?其實這點是針對第一點來說的,能夠動態(tài)地添加屬性和方法固然是增加了靈活性。可是我們討論一種情況,100個人同時來開發(fā)一個Javascript的項目,很多沒經(jīng)驗的人愛上了玩轉(zhuǎn)prototype,一個人往這個類里加一個方法,還面向?qū)ο竺矗?