3

他の多くのスクリプトを含むページで使用される外部JavaScriptファイルがあります。私のスクリプトには、イベントをリッスンする多くのjQueryが含まれており、設計上、多くのグローバル変数が宣言されています。私はベストプラクティスの記事を読んでいますが、「グローバル名前空間の汚染」と不注意なスクリプトの相互作用について多くのことが言われています。

JavaScriptファイルを次のように囲む(カプセル化する)ための最良の方法は何ですか?

  • エンクロージャー外のいくつかの変数にはまだアクセスできます
  • jQueryイベントリスナーは正しく機能します

私は自由にコードを開示することはできないので、一般的な回答でもありがたいです。さらに、スクリプトをページ上の他のスクリプトに対して脆弱にするためのその他のヒントを歓迎します。

通常のJavaScriptのエンクロージャースタイルを見つけましたが、jQueryを使用するとこれが複雑になりますか?

4

6 に答える 6

1

1つの方法は、次のように名前空間を作成することです。

var MyNamespace = {
    doSomething: function() {},
    reactToEvent: function() {},
    counter: 0
}

名前空間を使用して関数または変数を参照する必要がありますMyNamespace.reactToEventwindowこれは、 (すべての対立がある場所で)通常持っているものを分離するためにうまく機能します。

于 2011-06-10T15:27:41.677 に答える
1

コードを匿名のJavascript関数でラップし、外部に公開したいものだけを返すことができます。varグローバル変数にプレフィックスを付けて、無名関数のスコープ内にのみ残るようにする必要があります。このようなもの:

var myStuff = (function() {

   var globalVar1;
   var globalVar2;
   var privateVar1;

   function myFunction() {
     ...
   }

   function myPrivateFunction() {
     ...
   }

   return {
      var1: globalVar1,
      var2: globalVar2,
      myFunction: myFunction
   };

})();

myStuff.var1これで、にアクセスできますmyStuff.myFunction()

于 2011-06-10T15:29:23.597 に答える
1

一般に、これは要約すると、オブジェクトを「名前空間」にカプセル化することです。この用語はJavaScriptの公式のセマンティクスではなく、基本的なオブジェクトのカプセル化によって実現されるものであるため、ここでは引用符を使用します。

これを行うにはいくつかの方法があり、最終的には個人的な好みになります。

1つのアプローチは、基本的なJSオブジェクトを使用し、その中にすべてを保持することです。オブジェクトの名前はセマンティックであり、オブジェクトに何らかの意味を与える必要がありますが、それ以外の目的は、独自のコードをラップして、グローバル名前空間から除外することです。

var SomeName = {
    alpha: 1,
    beta: {a: 1, b: 2},
    gamma: function(){ 
        SomeName.alpha += 1;
    }
}

この場合、SomeNameのみがグローバル名前空間にあります。このアプローチの1つの欠点は、名前空間内のすべてがパブリックであり、「this」を使用する代わりに、オブジェクトを参照するために完全な名前空間を使用する必要があることです。たとえば、SomeName.gammaでは、SomeName.alphaを使用してアルファの内容。

もう1つのアプローチは、名前空間をプロパティを持つ関数にすることです。このアプローチの優れた機能は、クロージャを介して「プライベート」変数を作成できることです。また、完全な名前空間参照なしで、閉じられた関数と変数にアクセスできます。

var SomeName = (function(){
   var self = this;
   var privateVar = 1;
   var privateFunc = function() { };   

   this.publicVar = 2;
   this.publicFunc = function(){
       console.log(privateVar);
       console.log(this.publicVar); // if called via SomeName.publicFunc

       setTimeout(function(){ 
           console.log(self.publicVar);
           console.log(privateVar);
       }, 1000);
   };
}();

このアプローチのもう1つの利点は、使用するグローバル変数を保護できることです。たとえば、jQueryと、$変数を作成する別のライブラリを使用する場合、次の方法で$を使用するときにjQueryを参照していることを常に保証できます。

var SomeName = (function($){
    console.log($('div'));
})(jQuery);
于 2011-06-10T15:37:30.403 に答える
0

名前空間の汚染をカプセル化または制限する2つの方法

1)1つのグローバル変数を作成し、必要なものをすべて詰め込みます。

var g = {};
g.somevar = "val";
g.someothervar = "val2";
g.method1 = function() 
{
   // muck with somevar
   g.somevar = "something else";
};

2)インラインスクリプトの場合、呼び出される関数の範囲を制限することを検討してください。

<script>
(  
   function(window)
   {
      // do stuff with g.somevar
      if(g.somevar=="secret base")
        g.docrazystuff();      

   }
)();  // call function(window) then allow function(window) to be GC'd as it's out of scope now
</script>
于 2011-06-10T15:27:45.290 に答える
0

RequireJSを使い始めたばかりで、今ではそれに夢中になっています。

これは基本的に、モジュラーJavaScript形式の依存関係管理システムです。そうすることで、グローバル名前空間へのアタッチを事実上排除できます。

すばらしいのは、ページ上の1つのスクリプトのみを参照してrequire.jsから、最初に実行するスクリプトを指定することです。そこからそれはすべて魔法です...

実装スクリプトの例を次に示します。

require([
   //dependencies
   'lib/jquery-1.6.1'
], function($) {
   //You'll get access to jQuery locally rather than globally via $


});

RequireJS APIを読んで、これが適切かどうかを確認してください。私は今、このようにすべてのスクリプトを書いています。各スクリプトの上部で、依存関係がサーバー側の言語(JavaまたはC#)に類似していることが正確にわかっているので、これはすばらしいことです。

于 2011-06-10T15:28:28.947 に答える
0

これは、あなたが言及したのと同じ理由で、jQueryプラグインの一般的な方法です。

;(function ($) {

    /* ... your code comes here ... */

})(jQuery);

これは即時機能です。内部で「グローバル」変数を宣言すると、それらはこのクロージャに対してローカルになります(内部で作成するコードでは「グローバル」のままです)。イベントリスナーはここでも機能し、実際のグローバル変数に到達することができます。

于 2011-06-10T15:28:30.717 に答える