2013-08-29 65 views
2

首先我不確定這是正確使用這個庫的方式。我想在模塊中定義多個函數/靜態方法,並在模塊範圍內使用它們。例如:RequireJS模塊中的自引用

define({ 
     foo: function() { 
      return "Hello"; 
     }, 

     bar: function() { 
      alert(this.foo()); 
     } 
}); 

Main.js

require(['foobar'], function(foobar) { 

     foobar.bar(); // works 
     $('body').click(foobar.bar); // crash - Object #<HTMLBodyElement> has no method 'foo' 

}); 

如果bar()由事件觸發的,因爲很明顯this將意味着什麼在範圍不同此代碼將無法正常工作。是否有任何引用已定義對象的全局變量,並允許我從define()代碼中訪問方法和屬性?

回答

4

編輯:有關this的信息,請參閱下文。

您可以通過使用函數來獲得內部作用域。您可能想要聲明您的模塊是這樣的:

define((function() { var self = { // this line is changed 
     foo: function() { 
      return "Hello"; 
     }, 

     bar: function() { 
      alert(self.foo()); 
     } 
}; return self; }())); // and this 

這看起來很糟糕,我承認。要點是,它存儲對你返回的對象的引用,並用它來調用foo。我不確定你是否希望它像這樣...但它有效。


注意:這部分是關於處理JS中的this。查看評論爲什麼這個問題不再與這個問題有關。

問題實際上是在main.js,而不是在你的模塊。問題是JS如何處理this。這是不是與大多數其他語言相同!在JS中的this是其中函數是的上下文,其被稱爲,其中它不是定義的。您可以將apply函數用於其他對象,即使沒有這個函數也是如此。

你的情況,你想bindbarfoobar對象,因此在barthis是正確的對象。對此,您使用功能bind。它會創建一個新的函數,並將上下文設置爲您指定的對象。例如:

function doubleMe() { return this * 2; } 

您可以通過這樣調用這個函數:

doubleMe.apply(5) // returns 10 

你也可以這樣做:

var giveMeTen = doubleMe.bind(5); 

現在giveMeTen是一個函數,如果執行返回10。我建議你閱讀更多關於這個話題,this處理是怪在第一,但美的,如果理解;-)


關於你的代碼,我會寫:

require(['foobar'], function(foobar) { 

     foobar.bar(); 
     $('body').click(foobar.bar.bind(foobar)); 
}); 

注意jQuery將this設置爲已在click()處理程序中單擊的元素。

+0

這個例子將工作嗨Thriqon,謝謝你的回答。我明白爲什麼「this」會在不同的環境中發生變化,儘管我不知道bind(),所以非常感謝。我的例子是故意簡化和你的解決方案的工作,但我不想在我的真實例子中用bind()覆蓋「this」。我想知道事件來自哪裏,「這」很好。我真正需要做的是訪問模塊代碼。我知道我不會這樣做,但這是我的問題。在這個特定的上下文中引用foobar.foo()的最好方法是什麼。我希望澄清一點。 –

+0

@LukaszKujawa,我編輯了我的答案。這是你認爲的原因嗎? – thriqon

2

不知道你在這裏試圖完成什麼,也許更多的背景下你正在嘗試做什麼,我們可以給你更準確的諮詢。

然而,這裏就是我通常做模塊,requireJS(類,大部分)

if (typeof define === "function" && define.amd) { 
    define("module", function() { 
     var MyModule = function(){ 
      this.foo = function(){ 
       return "Hello!"; 
      }; 
      this.bar = function(){ 
       return this.foo(); 
      }; 
     } 

     return MyModule; 
    }); 
} 

現在使用:

require("module", function(MyMod){ 
    var a = new MyMod(); 
    console.log(a.bar()); 
} 

希望這有助於。 (你大概可以猜到如何使用封閉式示波器製作單件)

+0

弗雷德裏克你好,謝謝你的回答。對不起,不夠清楚。我編輯了我的問題並添加了main.js。如果foobar.bar被click()事件觸發,腳本將崩潰。在這種情況下,什麼是最好的替代「這個」。 –

+0

如果我將「return this.foo()」替換爲「return MyModule.foo()」 –

2

這可以通過傳遞一個函數來定義(這個函數被稱爲定義函數)。在定義函數內部:

  1. 定義你想在模塊中使用的函數。
  2. 使定義函數返回一個具有您希望模塊公開的功能的對象。在這裏,您要返回的對象中,可以調用上一步中定義的函數。

    define(function() { 
        function foo() { 
         return "Hello"; 
        }; 
    
        return { 
         bar: function() { 
          alert(foo()); 
         } 
        } 
    });