2012-01-12 15 views
0

以下の例を考えてみてください(jsfiddleリンクを使用している場合は右の「コンテンツ」をクリックしてください)、は、clickHelper()に達したときに範囲外になるのはなぜですか?jQueryプラグインのスコープに関する問題

私はそれを解決する2つの方法が考えられます。(1)引数として渡すことができます。または(2)var self;をプラグインの内側に定義することができます(上記function clickHelper())。私の実際の実装では、私はすでに引数の束とヘルパー関数の束を持っているので、私は、しかし#1を行うにはしたくない

...私はどこにでも周りselfを渡すことを避けるためにスコープを使用することを期待していました。

#このプラグインがページ上の複数の要素に使用されているようで、競合条件が存在する可能性がありますので#2を使用したくありません... jQueryにはプラグインのインスタンスが1つあり、したがってvar selfは1回だけ存在します。

私は基本的に、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:あなたは余分な引数を気にしない場合は#2が実証されhereとして競合状態/スレッドセーフな問題がないので#1は、おそらく最善の策である(クリックコンテンツ1、OK、そしてコンテンツ2は本当に速い)。あなたのヘルパーメソッドがあなたのハンドラメソッドをサポートしている場合には、あなたのハンドラメソッドの内部にヘルパーメソッドを定義して#2で逃げることができます(here)。そして、#3、私は通常、clickHelper()のようなJavaScript関数を呼び出すのではなく、ちょうど適切なクロージャーfunction(this) { var self = this; clickHelper() };を使用すると思います。

答えて

1

Guide on closures and scoping

変数は、それらが作成された機能にのみ使用可能です。したがって、selfclickHelperの中に作成すると、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

+0

@ Langdon heh、私はあなたの全体の質問を読むべきです、私はちょうどあなたが提案した解決策2の下にあったことにも気付いた。私はそれがあなたのプラグインがどのように動作するかに依存していると思います。渡されたさまざまな要素が新しいインスタンスを作成すると仮定します。 – Loktar

+0

スレッドセーフではありません...私はsetTimeoutを使ってajaxリクエストを模倣しています... http://jsfiddle.net/QZc9v/2/コンテンツ1をクリックしてからコンテンツ2を1秒以内にクリックすると、両方の "コールバック" 「a2」がクリックされたと表示されます。私はこの「ヘルパー」の方法を引き続き使用すれば、私は自分自身を引数として渡す**を持っていると思います。 – Langdon

関連する問題