2012-01-12 55 views
0

給出以下示例(如果您使用jsfiddle鏈接,請單擊右側的「content」),爲什麼self在達到clickHelper()時不在範圍內? (1)我可以通過它作爲參數,或者(2)我可以在插件的內部定義var self;(上面的function clickHelper())。我可以通過兩種方法來解決這個問題。jQuery Plugin Scoping問題

雖然我不想做#1,因爲在我真正的實現中,我已經有了一大堆參數和一堆幫助函數......我希望能夠使用範圍來避免在任何地方傳遞self

而我不想使用#2,因爲它似乎是如果這個插件用於頁面上的多個元素,可能有競爭條件......我的假設是,jQuery有1個插件實例,因此var self只會存在一次。

我基本上是尋找最佳做法,保持this範圍內爲jQuery插件引發的點擊事件。

http://jsfiddle.net/QZc9v/

<div id="a1"> 
    content 
</div> 

<script type="text/javascript">= 
    function info(n, s) { 
     var id = (typeof (s.id) == "undefined") ? '' : ': ' + s.id; 
     alert(n + ': ' + s + ': ' + typeof (s) + id); 
    } 

    (function ($) {  
     $.fn.myPlugin = function() { 
     function clickHelper() { 
      info('self in the Helper...', self); 
      self.innerHTML += '2'; 
     } 
     function clickHandler() { 
      var self = this; 
      info('self in the Handler', self); 
      self.innerHTML += '1'; 
      clickHelper(); 
     } 
     this.bind('click', clickHandler); 
     }; 
    }(jQuery)); 

    $(function() { 
     $('#a1').myPlugin(); 
    }); 
</script> 

ETA:#1可能是最好的選擇,如果你不介意額外的參數,因爲#2確實競爭條件/線程安全的問題,這表現here(點擊內容1,好,然後內容2真的很快)。您可以通過在您的處理程序方法中定義助手方法來獲得#2,如演示here所示,如果您的所有助手方法都支持您的處理程序方法,該方法可能適用於您。而且,我猜想,不是像通常那樣調用JavaScript函數clickHelper(),而是使用正確的關閉function(this) { var self = this; clickHelper() };

回答

1

Guide on closures and scoping

變量只適用於它們所創造的功能。因此,通過在clickHelper內部創建self,您只能將其作爲局部變量用於clickHelpers函數。

通過將其移動到myPlugins範圍內,它現在可以嵌套函數訪問。

Live Demo

$.fn.myPlugin = function() { 
     var self = {}; // self declared here instead can be used within this scope now 
     function clickHelper() { 
      info('self in the Helper...', self); 
      self.innerHTML += '2'; 
     } 
     function clickHandler() { 
      self = this; 
      info('self in the Handler', self); 
      self.innerHTML += '1'; 
      clickHelper(); 
     } 
     this.bind('click', clickHandler); 
    }; 
+0

所以,在我的問題是#2。當處理jQuery插件時,在這種情況下'var self'不是「線程安全」的嗎? – Langdon 2012-01-12 19:37:53

+0

@Langdon嘿,我應該讀完你的整個問題,我也注意到它是在你提出的解決方案2下。我想這取決於你的插件如何工作,我會假設爲傳遞的不同元素創建一個新的實例。 – Loktar 2012-01-12 19:39:42

+0

它不是線程安全的...我用setTimeout來模仿ajax請求... http://jsfiddle.net/QZc9v/2/如果你點擊內容1,然後在一秒內點擊內容2 ...「回調」會說「a2」被點擊。如果我繼續使用這種「幫手」方法,我想我**有**作爲參數傳遞自我。 – Langdon 2012-01-12 19:42:43