日韩黑丝制服一区视频播放|日韩欧美人妻丝袜视频在线观看|九九影院一级蜜桃|亚洲中文在线导航|青草草视频在线观看|婷婷五月色伊人网站|日本一区二区在线|国产AV一二三四区毛片|正在播放久草视频|亚洲色图精品一区

分享

原型-盡人事以聽天命

 WindySky 2009-07-03

原型

在使用JavaScript的面向?qū)ο缶幊讨?,原型?duì)象是個(gè)核心概念。在JavaScript中對(duì)象是作為現(xiàn)有示例對(duì)象(即原型)的副本而創(chuàng)建的,該名稱就來自于這一概念。此原型對(duì)象的任何屬性和方法都將顯示為從原型的構(gòu)造函數(shù)創(chuàng)建的對(duì)象的屬性和方法??梢哉f,這些對(duì)象從其原型繼承了屬性和方法。當(dāng)您創(chuàng)建如下所示的新Dog對(duì)象時(shí):

 

Js代碼 復(fù)制代碼
  1. var buddy = new Dog('Buddy');  

 

buddy所引用的對(duì)象將從它的原型繼承屬性和方法,盡管僅從這一行可能無法明確判斷原型來自哪里,對(duì)象buddy的原型來自構(gòu)造函數(shù)(在這里是函數(shù)Dog)的屬性。

在JavaScript中,每個(gè)函數(shù)都有名為"prototype"的屬性,用于引用原型對(duì)象。此原型對(duì)象又有名為"constructor"的屬性,它反過來引用函數(shù)本身。這是一種循環(huán)引用,圖3更好地說明了這種循環(huán)關(guān)系。



 圖 3 每個(gè)函數(shù)的原型都有一個(gè) Constructor 屬性 

現(xiàn)在,通過"new"運(yùn)算符用函數(shù)(上面示例中為Dog)創(chuàng)建對(duì)象時(shí),所創(chuàng)建的對(duì)象將繼承Dog.prototype屬性。在圖3中,可以看到Dog.prototype對(duì)象有一個(gè)回指Dog函數(shù)的構(gòu)造函數(shù)屬性。這樣,每個(gè)Dog對(duì)象(從Dog.prototype繼承而來)都有一個(gè)回指Dog函數(shù)的構(gòu)造函數(shù)屬性。圖4中的代碼證實(shí)了這一點(diǎn)。圖5顯示了構(gòu)造函數(shù)、原型對(duì)象以及它們創(chuàng)建的對(duì)象之間的這一關(guān)系。

Js代碼 復(fù)制代碼
  1. var spot = new Dog(“Spot”);   
  2.   
  3. // Dog.prototype is the prototype of spot   
  4. alert(Dog.prototype.isPrototypeOf(spot)); // 說明spot對(duì)象是從原型繼承來的   
  5.   
  6. // spot inherits the constructor property   
  7. // from Dog.prototype   
  8. alert(spot.constructor == Dog.prototype.constructor);    
  9. /*  
  10.  * 上例說明:  
  11.  * 說明構(gòu)造函數(shù)都有一個(gè)名為"prototype"的屬性,該屬性指向原型,   
  12.  * 而原型又有一個(gè)指向構(gòu)造函數(shù)的屬性"constructor",很顯然這是  
  13.  * 一個(gè)圈(循環(huán)引用)。  
  14.  */    
  15. alert(spot.constructor == Dog);    
  16. /*  
  17.  * 上例說明:  
  18.  * 因?yàn)槊總€(gè)對(duì)象都繼承自原型,所以每個(gè)對(duì)象都從原型中繼承了constructor  
  19.  * 屬性,而這個(gè)屬性指向構(gòu)造函數(shù)。  
  20.   */  
  21.   
  22. // But constructor property doesn’t belong   
  23. // to spot. The line below displays “false”   
  24. alert(spot.hasOwnProperty(“constructor”));    
  25.   
  26. // The constructor property belongs to Dog.prototype   
  27. // The line below displays “true”   
  28. alert(Dog.prototype.hasOwnProperty(“constructor”));   
  29.   
  30. / *   
  31.   * 上面兩個(gè)例子第一個(gè)alert彈出的提示是false,第二個(gè)是true,   
  32.   * 這再次說明了,"constructor"屬性不是對(duì)象本身的屬性,   
  33.   * 而是來自于對(duì)象的原型。   
  34.   */  

 



 圖 5 實(shí)例繼承其原型

某些讀者可能已經(jīng)注意到圖4中對(duì)hasOwnProperty和isPrototypeOf方法的調(diào)用。這些方法是從哪里來的呢〉它們不是來自Dog.prototype。實(shí)際上,在Dog.prototype和Dog實(shí)例中還可以調(diào)用其他方法,比如:toString()、toLocaleString和valueOf,但它們都不來自Dog.prototype。您會(huì)發(fā)現(xiàn),就像.NET Framework中的System.Object充當(dāng)所有類的最終基類一樣,JavaScript中的Object.prototype是所有原型的最終基礎(chǔ)原型。(Object.prototype的原型是null)

在此示例中,請(qǐng)記住Dog.prototype是對(duì)象。它是通過調(diào)用Object構(gòu)造函數(shù)創(chuàng)建的(盡管它不可見):

Js代碼 復(fù)制代碼
  1. Dog.prototype = new Object();  

 因此,正如Dog實(shí)例繼承Dog.prototype一樣,Dog.prototype繼承Object.prototype。這使得所有Dog實(shí)例也繼承了Object.prototype的方法和屬性。所以每個(gè)Dog實(shí)例也就繼承了我們上面說的toString、toLocaleString、hasOwnProperty方法了。

每個(gè)JavaScript對(duì)象都繼承一個(gè)原型鏈,而所有原型都終止于Object.prototype。注意,迄今為止您看到的這種繼承是活動(dòng)對(duì)象之間的繼承。它不同于繼承的常見概念,后者是指在聲明類時(shí)類之間的發(fā)生的繼承,因此,JavaScript繼承動(dòng)態(tài)性更強(qiáng)。它使用簡(jiǎn)單算法實(shí)現(xiàn)這一點(diǎn),如下所示:當(dāng)您嘗試訪問對(duì)象的屬性/方法時(shí),JavaScript將檢查該屬性/方法是否是在該對(duì)象中定義的。如果不是,則檢查對(duì)象的原型,如果還不是,則檢查該對(duì)象的原型的原型,如此繼續(xù),一直檢查到Object.prototype。圖6說明了此解析過程。


圖 6 在原型鏈中解析 toString() 方法

JavaScript動(dòng)態(tài)地解析屬性訪問和方法調(diào)用的方式產(chǎn)生了一些特殊效果:

  • 繼承原型對(duì)象的對(duì)象上可以立即呈現(xiàn)對(duì)原型所作的更改,即使是在創(chuàng)建這些對(duì)象之后。
  • 如果在對(duì)象中定義了屬性/方法 X,則該對(duì)象的原型中將隱藏同名的屬性/方法。例如:通過在Dog.prototype中定義toString方法,可以改寫Object.prototype的toString方法。
  • 更改只沿一個(gè)方向傳遞,即從原型到它的派生對(duì)象,但不能沿相反方向傳遞。

圖7說明了這些效果。圖7還顯示了如何解決前面遇到的不需要的方法實(shí)例的問題。通過將方法放在原型內(nèi)部,可以使對(duì)象共享方法,而不必使每個(gè)對(duì)象都有單獨(dú)的函數(shù)對(duì)象實(shí)例。在此示例中,rover和spot共享getBreed方法,直至在spot中以任何方式改寫toString方法。此后,spot有了它自己版本getBreed方法,但rover對(duì)象和用新GreatDane創(chuàng)建的后續(xù)對(duì)象仍共享在GreatDane.prototype對(duì)象中定義的那個(gè)getBreed方法實(shí)例。

Figure 7  繼承原型

Js代碼 復(fù)制代碼
  1. function GreatDane() { }   
  2.   
  3. var rover = new GreatDane();   
  4. var spot = new GreatDane();   
  5.   
  6. GreatDane.prototype.getBreed = function() {   
  7.     return 'Great Dane';   
  8. };   
  9.   
  10. // Works, even though at this point   
  11. // rover and spot are already created.   
  12. alert(rover.getBreed());   
  13.   
  14. // this hides getBreed() in GreatDane.prototype   
  15. spot.getBreed = function() {   
  16.     return 'Little Great Dane';   
  17. };   
  18. alert(spot.getBreed());    
  19.   
  20. // but of course, the change to getBreed    
  21. // doesn’t propagate back to GreatDane.prototype   
  22. // and other objects inheriting from it,   
  23. // it only happens in the spot object   
  24. alert(rover.getBreed());  

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類似文章 更多