2014-10-04 48 views
9

下面的兩個代碼塊在上下文中工作,並且看起來功能上完全相同。據我瞭解js prototypes相當不錯,所以我不問他們本身(除非唯一的區別)。viewmodel .prototype .function vs self .function in viewmodel?

相反,如以下所示比較兩個簡單的方法把一個方法上的圖模型,是否有任何影響/對Knockout,例如差異綁定時間?

定義([ 「敲除」, 「文本./ home.html做爲!」],功能(KO,homeTemplate){// < - 一個AMD Module

function HomeViewModel(route) { 
      var self = this; 
      self.message = ko.observable('Snacks!'); 

      self.eatSomething = function() { 
        self.message('Yum, a viewmodel snack.'); 
      }; 
    } 
    return { viewModel: HomeViewModel, template: homeTemplate }; 
}); 

與添加

定義([ 「敲除」, 「!文本./ home.html做爲」],功能(KO,homeTemplate){

0123:通過原型方法

});

(該代碼是Yeoman's腳手架輸出的一個簡單的MOD經由Knockout generator,它創建的鍋爐板代碼爲knockout component,一個相當新的(KO 3.2)和非常受歡迎的特徵。一個好的KO分量解釋器是here.

回答

11

在第一個例子,因爲該函數使用self(被設定爲新的實例的引用),而不是this,無論功能如何被調用/約束,它總是正確地設置自己的message觀察到。

在第二個示例中,當正常綁定到像data-bind="click: eatSomething"這樣的函數時,您將得到相同的結果。敲除調用值爲this的函數等於當前數據。

如果您有一個場景需要從不同的上下文中調用該函數(也許您的視圖模型有一個您正在使用的子對象with或模板)。那麼你可以使用像data-bind="click: $parent.eatSomething"這樣的綁定。 KO仍然會調用this等於當前數據的功能(這不會是$parent),所以您會遇到問題。把函數的原型,雖然的

一個優點是,如果你創建的HomeViewModel許多情況下,他們都分享通過其原型相同eatSomething功能,而不是每個實例取得自己的eatSomething功能的副本。這可能不是您的情況,因爲您可能只有一個HomeViewModel

您可以通過調用它來確保上下文正確:data-bind="click: $parent.eatSomething.bind($parent)。使用此調用將創建一個新的包裝函數,該函數使用適當的上下文(值爲this)調用原件。或者,您也可以將它綁定到視圖模型中,以使綁定更清晰。無論哪種方式,您都會失去將其放在原型上的一些價值,因爲您正在爲每個實例創建包裝函數。至少該功能的「膽量」只會在原型上存在一次。

我傾向於在我的代碼中使用原型,但毫無疑問,使用self技術(或類似揭示模塊模式)可以減少您對值this的關注。

+0

有用的說明 - 你是什麼意思**'揭示模塊模式'**?順便說一句,我只是偶然發現了你的[Knockout AMD Helpers](https://github.com/rniemeyer/knockout-amd-helpers) - 看起來非常有用 - 尤其是像包含自己模板的模塊。所以也非常感謝! – 2014-10-06 22:04:26

+0

有幾個鏈接描述了揭示模塊模式,這裏是一個:http://weblogs.asp.net/dwahlin/techniques-strategies-and-patterns-for-structuring-javascript-code-revealing-module-模式。基本上,你可以定義你想要的任何方法,並且可以直接引用變量。然後,您將模塊中的公共「API」與您想要公開的方法一起返回,並使用您想要公開的任何名稱。希望有所幫助! – 2014-10-07 14:13:52

+1

@ RPNiemeyer - 你沒有寫關於這個確切問題的博客嗎?我想我回想起過去一直在使用Google,並且這是我最終選擇的地方 – user210757 2015-03-03 15:10:06

相關問題