2013-12-12 137 views
3

我有一個Backbone Marionette應用程序,下面定義了一個模塊。當我運行這個應用程序時,控制檯日誌語句打印出@作爲窗口對象。當運行list方法時,我認爲this@)會引用List.Controller對象。我錯過了什麼?爲什麼`this`引用全局對象?

### 
The Header list controller. 
### 
define [ 
    'cs!app', 
    'cs!./view', 
    'cs!modules/header/entities' 
], (
    App, 
    View 
) -> 
    App.module 'Header.List', (List, App, Backbone, Marionette, $, _) -> 
    List.Controller = 
     list: -> 
     console.log(@) 
     headers = App.request 'header:entities' 
     view = new View.Headers {collection: headers} 
     App.headerRegion.show view 

     setActiveHeader: (headerUrl) -> 
     headers = App.request 'header:entities' 
     header = headers.find (header) -> (header.get 'url') == headerUrl 
     header.select() 
     headers.trigger 'reset' 

    App.commands.setHandler 'header:setActive', (headerUrl) -> 
     List.Controller.setActiveHeader headerUrl 

    App.Header.List.Controller 

更新

這是調用列表法模塊:

### 
The Header module. 
### 

define [ 
    'cs!app', 
    'cs!./list/controller' 
], (
    App, 
    listController 
) -> 
    App.module 'Header', (Module, App, Backbone, Marionette, $, _) -> 
    Module.startWithParent = false 

    App.module 'Routers.Header', (ModuleRouter, App, Backbone, Marionette, $, _) -> 
    class ModuleRouter.Router extends Marionette.AppRouter 
     appRoutes: {} 

     executeAction = (action, args) -> 
     action(args) 

     API = 
     list: -> 
      executeAction listController.list 

     App.Header.on 'start', -> 
     API.list() 

     App.addInitializer -> 
     new ModuleRouter.Router {listController: API} 

    App.Header 
+0

哪裏呼籲函數列表? – ekeren

+0

我在我的更新中添加了呼叫。 – Erik

回答

2

問題是調用與window(全局)上下文對象listController的方法list

這是因爲您調用的方法是這樣的:executeAction listController.listexecuteAction這只是調用方法正常方式:action(args)

您可以綁定方法的類(_.bind)或用js Functioncallapply方法(綁定的方法是更容易):

綁定(_.bind(action, context)

executeAction _.bind(listController.list, listController) 

調用(或應用)與另一個上下文(method.call(context, arg1, ..)method.apply(context, argsArray)

+0

我用過你的最後一個例子,它的作用就像一個魅力 - 我想我明白現在發生了什麼。我唯一看到的是ekerens選項。 – Erik

+0

我用這個選項去了。我也在研究與executeAction一塊使用的額外間接級別的要求。感謝所有人的幫助。 – Erik

0

this未綁定到該函數被調用,取決於函數是如何被調用。您可以將其視爲隱式傳遞給該函數的額外參數。

在這種情況下,我認爲你使用controller()來調用你的函數。通過調用函數作爲方法(如foo.bar()foo["bar"]())或通過call()apply()明確設置,可以設置值爲this。你的呼叫既不這麼做,也不會回到全局對象。

here

+0

我在更新中添加了我的電話。因爲我使用listController。列表中,我認爲'this'將被綁定到listController。 – Erik

+0

我只是注意到你正在使用'requirejs'。看起來'requirejs'不會對'this'關鍵字進行任何綁定。對於沒有requirejs的相同代碼,您將得到您的控制器obj。 – user2503775

+1

蘆葦更在這裏:http://stackoverflow.com/questions/14650746/can-the-this-keyword-be-used-inside-a-requirejs-module – user2503775

1

你應該在初始化函數中使用_.bindAll(this),只需添加:

initialize:-> 
    _.bindAll(this, "list") // Like @mu mentioned in the comment, function name is required 

編輯

雖然@ KIT-O是正確的,調用者可以結合使用_.bind功能的功能控制器。這不應該是呼叫者的責任,該功能需要綁定到正確的上下文,呼叫者不應該關心/瞭解它。

這就是爲什麼我喜歡_.bindAll解決方案雖然增加了更多的樣板代碼骨幹

+0

我通過將App.Header.List.addInitializer - > _.bindAll(App.Header.List.Controller,'list','setActiveHeader')添加到我的Header列表控制器中來實現此目的。這很有效,但與KiT O的解決方案相比似乎很麻煩 - 我不得不維護函數列表。 – Erik

+0

這不適用於較新版本的Underscore:[「** methodNames **是必需的。」](http://underscorejs.org/#bindAll) –

+0

@Erik - 我不同意:),請參閱編輯我在哪裏解釋爲什麼 – ekeren

相關問題