JavaScript:prototype屬性使用方法


參考:
http://bokee.shinylife.net/blog/article.asp?id=455
http://dev.csdn.net/article/84222.shtm
http://www.cnblogs.com/goody9807/archive/2007/04/16/715109.html

一、基本使用方法

      prototype屬性可算是JavaScript與其他面向對象語言的一大不同之處。

簡而言之,prototype就是“一個給類的對象添加方法的方法”,使用prototype屬性,可以給類動態地添加方法,以便在JavaScript中實現“繼承”的效果。

      具體來說,prototype 是在 IE 4 及其以后版本引入的一個針對於某一類的對象的方法,當你用prototype編寫一個類后,如果new一個新的對象,瀏覽器會自動把prototype中的內容替你附加在對象上。這樣,通過利用prototype就可以在JavaScript中實現成員函數的定義,甚至是“繼承”的效果。

      一個簡單的示例如下:

  1. Number.prototype.add = function(num){return(this+num);} 

 

這是對已有類添加方法。這樣寫,可以增強已有類的功能,例如可以給Array類增加push方法如下:

  1. Array.prototype.push = function(new_element){ 
  2.         this[this.length]=new_element; 
  3.         return this.length; 
  4.     } 

 

對於自定義的類(或者稱函數對象),也可以這樣寫:

  1. function MyApplication() { 
  2.     this.counter = 0; 
  3.     this.map = new GMap2(document.getElementById("map_canvas")); 
  4.       this.map.setCenter(new GLatLng(39.917,116.397), 14); 
  5.       GEvent.bind(this.map, "click", this, this.onMapClick); 
  6.     } 
  7.          
  8.     MyApplication.prototype.onMapClick = function() { 
  9.       this.counter++; 
  10.       alert("這是您第 " + this.counter + " 次點擊地圖"); 
  11.     } 

這里定義了創建地圖的類,並且為其定義了“單擊”事件的響應函數。

 

二、prototype的動態特性及弊端

     需要注意的是,prototype為我們提供了方便,使我們可以在類定義完成之后,仍可以隨時為其添加方法、屬性,隨時添加隨時使用——也就是prototype的定義具有動態性。但是越靈活的語言出現錯誤的可能性越大。這就需要我們在使用時,必須養成一些良好的習慣。

      “首先,如果可以動態添加屬性和方法,那么很容易讓人想到,當我調用時,我想要調用的屬性或者方法存在不?這是一個很嚴肅的問題,如果當我們調用時根本沒有該屬性或者方法,將可能導致我們的腳本down掉。” 對於這個問題,在使用時我們以后可以按照下面的寫法書寫:

  1. function MyObject(name, size) 
  2.     this.name = name; 
  3.     this.size = size; 
  4.  
  5. MyObject.prototype.height = "2.26 meters"
  6. MyObject.prototype.tellHeight = function() 
  7.     return "height of "+this.name+" is "+this.height; 
  8.  
  9. ///////使用 
  10. var myobj1 = new MyObject("haha", 3); 
  11. if (myobj1.tellHeight) 
  12.     domDiv.innerHTML += myobj1.tellHeight()+"; 

 

       屬性和方法在不在的問題簡單,可是屬性和方法變不變化的問題可就嚴重了。在不在我們可以檢測,變不變呢?比如,請看下面的代碼:

  1. function MyObject(name, size) 
  2.     this.name = name; 
  3.     this.size = size; 
  4.  
  5. MyObject.prototype.color = "red"
  6. MyObject.prototype.tellColor = function() 
  7.     return "color of "+this.name+" is "+this.color; 
  8.  
  9. var myobj1 = new MyObject("tiddles", "7.5 meters"); 
  10. domDiv.innerHTML += myobj1.tellColor()+"<br /><br />"
  11.  
  12.         
  13.  
  14.        MyObject.prototype.color = "green"
  15.  
  16.         
  17.  
  18.        domDiv.innerHTML += myobj1.tellColor()+"<br /><br />"

 

修改的是類MyObject的color屬性。但是你驚奇的會看到你之前實例化的對象myobj1的屬性值竟然也變化了:
color of tiddles is red
color of tiddles is green

上面是屬性,還有方法,方法也是可以變的!

  1. function MyObject(name, size) 
  2.     this.name = name; 
  3.     this.size = size; 
  4.  
  5. MyObject.prototype.color = "red"
  6. MyObject.prototype.tellColor = function() 
  7.     return "color of "+this.name+" is "+this.color; 
  8.  
  9. var myobj1 = new MyObject("tiddles", "7.5 meters"); 
  10. domDiv.innerHTML += myobj1.tellColor()+"<br /><br />"
  11.  
  12. MyObject.prototype.color = "green"
  13. MyObject.prototype.tellColor = function() 
  14.     return "your color of "+this.name+" is "+this.color; 
  15.  
  16. domDiv.innerHTML += myobj1.tellColor()+"<br /><br />"


這段代碼的結果是:

color of tiddles is red
your color of tiddles is green

Java和C#這些比較嚴格的語言,雖然降低了靈活性,但也減少了犯錯誤的可能。這樣,即使一個新手,他寫出的代碼也不會與高手差太多。但是,像Javascript這樣的腳本語言,由於太靈活,所以,一定要有好的代碼編寫習慣,否則出現了上面的問題,調試時可就難咯!

 

三、prototype的實現機制

可以說,prototype實際上是“引用”,而非“賦值”。也就是給一個類添加一個屬性或者方法,是給它添加了個引用,而非賦值一份給它。看看下面的這個例子:

  1. <html> 
  2. <head> 
  3. <meta http-equiv="content-type" content="text/html; charset=UTF-8"/> 
  4. <title>Test "prototype"</title> 
  5. <mce:script type="text/javascript"><!-- 
  6.         function ClassA() 
  7.         { 
  8.             alert("a"); 
  9.             this.a=function(){alert();}; 
  10.         } 
  11.         function ClassB() 
  12.         { 
  13.             alert("b"); 
  14.             this.b=function(){alert();}; 
  15.         } 
  16.  
  17.         ClassB.prototype.a=new ClassA();        //會導致彈出 a 對話框 
  18.         ClassB.prototype.xx = "xx"
  19.          
  20.         function initialize() 
  21.         { 
  22.             var objB1=new ClassB();                 //彈出 b 對話框 
  23.             var objB2=new ClassB();                 //彈出 b 對話框 
  24.             alert(objB1.a==objB2.a);                    //true 
  25.             alert(objB1.b==objB2.b);                //false 
  26.             alert("objB1.xx: " + objB1.xx + ", objB2.xx: " + objB2.xx); //objB1.xx: xx, objB2.xx: xx 
  27.             ClassB.prototype.xx = "yy"
  28.             alert("objB1.xx: " + objB1.xx + ", objB2.xx: " + objB2.xx); //objB1.xx: yy, objB2.xx: yy 
  29.             objB2.xx = "zz"
  30.             alert("objB1.xx: " + objB1.xx + ", objB2.xx: " + objB2.xx); //objB1.xx: yy, objB2.xx: zz 
  31.         } 
  32.      
  33. // --></mce:script> 
  34. </head> 
  35. <body> 
  36. <mce:script type="text/javascript"><!-- 
  37.         initialize(); 
  38.      
  39. // --></mce:script> 
  40. </body> 
  41. </html> 

 

其執行結果是依次彈出以下窗口:
a
b
b
true
false
objB1.xx: xx, objB2.xx: xx
objB1.xx: yy, objB2.xx: yy
objB1.xx: yy, objB2.xx: zz
相關的解釋已經注釋在代碼中。從上面的代碼可以發現,prototype只是給ClassB添加了ClassA實例的引用。因此,兩個ClassB的實例中的a實例相等。

同時,ClassA的構造函數只在添加引用時被執行一次,此后ClassB的對象實例化時,只執行ClassB的構造函數。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM