談談javascript原型構造機制

話題源於:js一個很奇怪的問題 

ecma太拙嘴饒舌,本文力圖用簡單的測試示例來說明問題 

任意創建一個函數,其原型prototype立刻被自動創建: 
Js代碼  收藏代碼
  1. function Coo(){};  
  2. alert(Coo.prototype.constructor); //=>function Coo(){}  


實例化Coo的原型prototype被置於作用域scope的最頂端: 
Js代碼  收藏代碼
  1. function Coo(){  
  2.     alert(Coo.prototype.constructor);  
  3. }  
  4. var c1 = new Coo();  // => function Coo(){ ..}  


在實例化Coo之前修改其原型prototype,其作用域scope頂端自動調整爲修改後的原型prototype,並且實例c1可沿原型鏈找到method方法 
Js代碼  收藏代碼
  1. function Coo(){  
  2.     alert(Coo.prototype.method); // => function(){} 作用域scope頂端自動調整爲修改後的原型prototyp  
  3. }  
  4. Coo.prototype = { method : function(){} }  
  5. var c1 = new Coo();  // => function(){}  
  6. alert(c1.method);  // => function(){}  


在實例化過程內部重新設置Coo的屬性prototype: 
Js代碼  收藏代碼
  1. function Coo(){  
  2.     alert(Coo.prototype.method); // => undefined 作用域scope頂端依舊爲默認自動創建的原型prototype  
  3.     Coo.prototype = { method : function(){} }   
  4. //注意:上面這行重新設置了Coo的[b]屬性[/b]prototype,  
  5. //它已不再是Coo自動創建或是自動調整後的原型prototype了——這正是javascript原型機制的核心  
  6. }  
  7. var c1 = new Coo();  // => function(){}  
  8. //所以,雖然貌似:  
  9. alert(c1.prototype.method) // => function(){}  
  10. //但此[b]屬性[/b]——"prototype"(),已非彼[b]原型[/b]——"prototype"了:  
  11. alert(c1.method); // => undefined  


所以在實例化過程內部,只能基於原型prototype來擴展或修改方法 
Js代碼  收藏代碼
  1. function Coo(){  
  2.     alert(Coo.prototype.method); // => undefined  
  3.     Coo.prototype.method = function(){}; // 在正宗原型prototype上擴展,非山寨!   
  4. }  
  5. var c1 = new Coo();  // => function(){}  
  6. alert(c1.prototype.method); // => function(){}  
  7. alert(c1.method); // => function(){};  


盤根究底,既然在實例化過程內部重新設置Coo的屬性prototype, 
那麼Coo的原型prototype又會去了哪兒呢? 
Js代碼  收藏代碼
  1. function Coo(){   
  2.     Coo.prototype = { method : function(){ alert("實例化中");} };  
  3. };  
  4. Coo.prototype = { constructor : Coo, method : function(){} }  
  5. var c1 = new Coo();  
  6. alert(c1.prototype.method); // => function(){ alert("實例化中");} 糟糕!  
  7. alert(c1.method); // => function(){} 謝天謝地!  
  8. alert(c1.constructor === Coo ); // => true; 原型鏈都還在,但它們似乎只是在內部被保存起來了  


囉嗦了一大堆,簡而言之: 
函數的原型prototype是在實例化(或執行函數自身)之前就被自動創建(可以被修改或重置引用)的。 
而在實例化(或執行函數自身)過程中,重置的prototype已淪爲一個普普通通的對象屬性了, 
但是他卻並不會干擾正常的javascript實例方法的原型鏈查找機制。
1 樓 lifesinger 2009-08-20  
zbm2001 寫道

實例化Coo的原型prototype被置於作用域scope的最頂端: 
Js代碼  收藏代碼
  1. function Coo(){  
  2.     alert(Coo.prototype.constructor);  
  3. }  
  4. var c1 = new Coo();  // => function Coo(){ ..}  



這個說法不嚴謹,Coo.prototype 是在 parse 階段就已添加,而不是 runtime 時才添加。 

比如: 
Js代碼  收藏代碼
  1. function Coo(){ }  
  2. debugger  


在 firebug 下,debugger 處已經可以看到 Coo.prototype 爲 Object 
 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章