首頁 > web前端 > js教程 > 主體

JavaScript 透過函數來實作定義類別實例用法詳解

伊谢尔伦
發布: 2017-07-21 17:19:43
原創
1888 人瀏覽過

先透過一個範例來說明: 

function myClass() 
{ 
var id = 1; 
var name = "johnson"; 
//properties 
this.ID = id; 
this.Name = name; 
//method 
this.showMessage = function() 
{ 
alert("ID: " + this.ID + ", Name: " + this.Name); 
} 
} 
var obj1 = new myClass(); 
var obj2 = new myClass();
登入後複製

function的定義其實相當於類別的建構函數,最後兩句是建立這個類別的實例。先分析第一句:var obj1 = new myClass(); 當用new建立類別的實例時,解釋器會先建立一個空的物件。然後執行這個myClass函數,並將this指標指向這個類別的實例。當碰到this.ID = id;和this.Name = name;及this.showMessage = function(){...}時,便會創建這兩個屬性,和這個方法,並把變量id,name的值一級函數的定義賦給這兩個屬性及這個函數物件(shwoMessage)。這個過程相當於初始化這個對象,類似C# 中的建構子。最後new回傳這個物件。再看第二句:var obj2 = new myClass(); 執行過程與上一句程式碼相同,即建立一個空對象,然後執行myClass這個函數,定義兩個屬性和一個方法。
從上面的分析可以看到,上面這種實作類別的方式,也就是在函數的定義中定義類別的屬性方法。存在著弊端。如果需要建立兩個或更多這個類別的實例時,上文是兩個,這些屬性會被重複的創建多次。
那麼要如何避免這種情況呢? prototype和它的名字一樣是一個原型,每一個function都有一個子物件prototype,它其實表示這個function物件的成員的集合,由於這裡我們使用function實作類別的,所以可以說prototype其實就是便是類的成員的集合。 prototype定義的屬性和方法執行在函式的建構體執行之前,所以當new一個物件之前,其實prototype的成員已經執行過了。先看一個例子: 

function myClass() 
{ 
//构造函数 
} 
myClass.prototype = 
{ 
ID: 1, 
Name: "johnson", 
showMessage: function() 
{ 
alert("ID: " + this.ID + ", Name: " + this.Name); 
} 
} 
var obj1 = new myClass(); 
var obj2 = new myClass();
登入後複製

類別的結構還是跟前面的例子相同,只不過這裡是利用了prototype來實作。還是先看最後兩句,前面說過,prototype是執行在函數構造體之前,即執行到var obj1 = new myClass();之前,這個類別已經有了ID,Name屬性和showMessage方法。執行者一句時執行過程如下,注意和前一個例子比較:首先還是創建一個空的對象,並把this指針指向這個對象。然後將函數的prototype物件的所有成員都賦給這個物件(注意沒有再建立這些成員)。然後執行函數體。最後new回傳這個物件。執行下一句時:同樣執行此過程,不會重複建立這些成員。
上面的程式碼還只是一個例子,在實際的專案中,可能出現的是類別中有大量的成員,同時可能需要建立大量的實例。這是prototype就會顯示其優越性了。另外上面的程式碼使用了大括號語法定義了prototype的成員,這樣看起來程式碼比較清楚。這是一種比較推薦的類別的設計模式。當然在眾多的專案中,可能還會發現更好的模式,我們也希望能有更優化的JavaScript的程式模式不斷推陳出新,也希望隨著時間的推移,各主流瀏覽器也對JavaScript的解析都標準,統一。
上面說過prototype定義的成員是發生在構造體之前,可以證明一下,在上面的例子中,構造體是空的,在構造函數中加入一句alert(this.Name);,當執行到var obj1 = new myClass();時,會看到彈出對話框,顯示正確的屬性值。
如下程式碼: 

function subClass(){ } 
subClass.prototype = 
{ 
Name: "sub" 
} 
function myClass() 
{ 
//构造函数 
} 
myClass.prototype = 
{ 
ID: 1, 
Name: "johnson", 
SubObj: new subClass(), 
showMessage: function() 
{ 
alert("ID: " + this.ID + ", Name: " + this.Name + "SubObj.Name:" + this.SubObj.Name); 
} 
} 
var obj1 = new myClass(); 
obj1.SubObj.Name = "XXX"; 
obj1.showMessage(); 
var obj2 = new myClass(); 
obj2.showMessage();
登入後複製

這裡在myClass定義了一個引用類型,其類型是我們自訂的一個subClass類,這個子類別中有一個Name屬性。由於prototype物件是共享的,按照我們上面的分析:在執行var obj1 = new myClass();時,會把myClass的prototype中的成員複製給這個obj1實例。但這裡SubObj是一個引用類型,在執行到var obj2 = new myClass();時,prototype中的ID,Name成員會複製到obj2中,但SubObj這個屬性不會複製過去,而是引用了prototype中的SubObj,所以因為上一句修改了obj1.Subobj.Name的值,所以在用new產生obj2實例時,引用到了修改後的值。
所以藉用prototype定義類別時,依然需要將屬性定義在建構體中,而將方法定義在該構造體的原型上。如下: 

function myClass(id, name) 
{ 
this.ID = id; 
this.Name = name; 
} 
myClass.prototype = 
{ 
showMessage: function() 
{ 
alert("ID: " + this.ID + ", Name: " + this.Name); 
}, 
showMessage2: function() 
{ 
alert("Method2"); 
} 
} 
var obj1 = new myClass(1, "johnson"); 
obj1.showMessage(); 
obj1.Name="John"; 
obj1.showMessage(); 
var obj2 = new myClass(2, "Amanda"); 
obj2.showMessage();
登入後複製

以上是JavaScript 透過函數來實作定義類別實例用法詳解的詳細內容。更多資訊請關注PHP中文網其他相關文章!

相關標籤:
來源:php.cn
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板
關於我們 免責聲明 Sitemap
PHP中文網:公益線上PHP培訓,幫助PHP學習者快速成長!