2012-08-03 92 views
2

似乎有很多技術用於創建客戶端對象。我發現真正令人困惑的是確定每種技術被稱爲什麼。我使用的原型JavaScript面向對象的編程技術,這叫做什麼?

MyObject.prototype.someMethod = function (e, a) { 
     ..... 
}; 

之前,但我也看到了在不同的創建這樣

MyObject.someMethod = function() { 
     .... 
} 

對象,什麼叫第二techinque,爲什麼會一個使用一個比其他?

+0

它直接連接屬性的構造函數,用'MyObject'構造不繼承在構造函數屬性的對象,但屬性在構造函數的原型中。 – Esailija 2012-08-03 17:51:05

+1

這些都不涉及OOP。他們完成不同的事情。 – 2012-08-03 17:52:03

+0

對象的屬性? – 2012-08-03 17:52:05

回答

4

第一個例子類似於定義類的方法。該類的每個實例都使用相同的代碼;這種方法中的this指向該方法被調用的實例。

第二種類似於在類上定義靜態方法。您調用方法類似

MyObject.someMethod();

它沒有意義來調用一個實例方法。

我想你可以調用第一個「原型方法」和第二個「構造函數/類方法」。

如果您在討論JavaScript時習慣使用經典的OO術語,這與JavaScript使用原型繼承有點尷尬,您可以調用第一個「實例方法」和第二個「靜態方法」。

+0

太棒了!我不知道我在網上搜索了多少簡單的解釋。 – NullReference 2012-08-03 18:48:59

1

最簡單的答案是,使用prototype關鍵字在對象上定義方法將允許將該方法用於從其繼承的所有對象。

JavaScript中沒有類,但可以通過使用原型對象(屬性)來模擬繼承。我們將爲所有從myObject派生的對象添加一個「方法」(你可以在jQuery加載後對jQuery執行此操作 - $ .prototype.method [$ .fn.method]將添加一個方法到所有jQuery對象,而不管它們何時被創建)。

myObject.method將只爲myObject添加一個「方法」,因爲它在執行代碼行時(靜態方法)。在該行執行之前調用的任何myObject都將無法訪問「method」。

1

JavaScript使用所謂的Prototypical Inheritance來實現性狀的繼承。考慮下面的例子:

Superclass = function() { 
    //constructor code 
} 

Superclass.prototype.toString=function() { 
    return "Derp!"; 
} 
Superclass.derp= function(){return 'herp!'} 



var instance = new Superclass(); 
instance.toString();//valid 
instance.derp();//fails 
1

有幾件事情在這裏。 首先,在擔心定義對象的方法之前,擔心對象的創建。

所以,有幾種創建對象的方法。首先,您可以創建一個內聯對象,藍色:

​​

您現在有一個全新的對象。 您可以在事後添加它來擴展該對象。

obj.property02 = "myOtherProperty"; 
obj.otherFunc = function() { return this.property02; }; 

但構建內聯對象的垮臺是所有屬性和方法都是100%公開。

爲了解決這個問題,你可以有一個構造函數來創建和返回一個對象。

var MakeWallet = function (starting_amount, pin) { 
    var balance = 0, 
     wallet = {}; 

    wallet.add = add_balance; 
    wallet.deduct = deduct_amount; 
    wallet.amount = check_balance; 

    return wallet; 

    function check_balance (pin) { /*...*/ } 
    function validate_pin (user_pin) { /*...*/ } 
    function add_balance (amount, pin) { /*...*/ } 
    function deduct_amount (amount, pin) { /*...*/ } 

}; 

var myWallet = MakeWallet(1, 9274); 

我得到什麼麻煩?所有的數據都是防篡改的。

用戶可能仍然可以重寫wallet.deduct,但他們實際上並不會獲得該引腳的實際價值,或者獲取錢包中的金額,或者獲取我不想要的任何內部函數包括我想要授權追蹤錢包的任何內部安全號碼或實體/序列號。

這就是以這種方式建設的好處。

同樣,我可以添加方法和屬性的錢包,後來:

myWallet.breakItOpen = function() { return this.balance; }; 
myWallet.stuffIt = function() { balance = 400000000; }; 

但是這兩個東西實際上是將具有原始myWallet內訪問變量或函數。
只有在創建時存在的功能纔有權訪問。

在其他更傳統的創建方法中,您可以使用類似構造函數,使用this

function MakeWalletClass (starting_amount, pin) { 
    var balance = 0, 
     serial_and_pin = generate_serial() + "_" + pin; 

    this.balance = balance; 
    this.checkBalance = function() { return this.balance; }; 
} 

var myWalletInstance = new MakeWalletClass(1, 1234); 

但是有一個問題:
myWalletInstance.balance是公開的。
任何人都可以看到它或改變它。
不好。

我們可以得到解決,通過這樣做:

function MakeWalletClass (starting_amount, pin) { 
    var balance = 0, 
     serial_and_pin = generate_serial() + "_" + pin; 

    this.checkBalance = function() { return balance; }; 
} 

var myWalletInstance = new MakeWalletClass(1, 1234); 

現在,this.checkBalance正在讀取隱藏balance變量,而不是一個公開編輯屬性。

現在,MakeWalletClass.prototype

當您使用的構造模式(即:一個函數,它增加了屬性this並返回this,或者不返回任何東西 - 它返回後臺this - ,被稱爲與new關鍵字),加入prototype屬性和方法將添加可用的屬性和方法每個您製作的對象的實例。

所以,如果您的銀行被稱爲「銀行鮑勃」,你可以添加:

MakeWalletClass.prototype.bankName = "The Bank of Bob"; 

現在的new MakeWalletClass();每一個實例都會有一個bankName財產,每個人都將是精確的,相同的值,並且每一個都將公開可用。

var yourWalletInstance = new MakeWalletClass(500, 2341); 
yourWalletInstance.bankName; // "The Bank of Bob"; 

prototype性能甚至,你讓你添加屬性的構造函數的原型對象可用。

您可以用相同的方法添加prototype方法。

var myWalletInstance = new MakeWalletClass(1, 1234); 
MakeWalletClass.prototype.getBalance = function() { return balance; }; 
myWalletInstance.getBalance(); // undefined; 

哎呀!
它不起作用。

原型功能可訪問ONLY公共性質(任何他們可以用this.XXX調用)。

因此,添加prototype屬性的好處是它們可以節省大量內存。 如果您的程序需要3000個錢包,並且您將prototype function添加到構造函數中,則該函數僅在內存中存在1次。

添加原型的缺點是它只能做公共事物,所以除非你想平衡或固定公共屬性(提示:不要),否則原型對於私人工作是無用的。

因此,對於那些3000個錢包,您需要處理餘額或銷的任何方法的3000個副本。

現在,你已經得到了這一切的理解,什麼prototype是...的真正區別:

MakeWalletClass.prototype.say_bankName = function() { /*...*/ }; 

MakeWalletClass.say_bankName = function() { /*...*/ }; 

是,prototype作品(wallet = new MakeWalletClass),並且MakeWalletClass的方法不會 - 僅當您需要附加到MakeWalletClass的函數時纔有用。

也許你想返回製成的錢包數的函數...