2012-04-25 4 views
0

私はJavaScriptとモジュールのパターンを学んでいますが、私のコードで間違いを犯しました。私の基本的なコードは次のようである:次にjavascript module pattern変数の範囲

(function(window,$){ 

//global menu object 
var menu = (function(){ 

    //menu tab component 
    var tab = (function(){ 

     //public properties 
     var tab = { 
      init:doStuff 
     } 

     //private properties 
     function doStuff(){ 
      alert("initialising Tab") 
     } 

     //return public properties 
     return tab; 
    })(); 

    //menu curtain component 
    var curtain = (function(){ 

     //public properties 
     var curtain = { 
      init:doStuff 
     } 

     //private properties 
     function doStuff(){ 
      alert("initialising Curtain") 
     } 

     //return public properties 
     return curtain; 
    })(); 

    //menu content component 
    var content = (function(){ 

     //public properties 
     var content = { 
      init:doStuff 
     } 

     //private properties 
     function doStuff(){ 
      alert("initialising Content") 
     } 

     //return public properties 
     return content; 
    })(); 

    //public properties 
    var menu = { 
     init:initialiseMenu 
    } 

    //private properties 
    function initialiseMenu(){ 
     //initialise each component of the menu system 
     tab.init(); 
     curtain.init(); 
     content.init(); 

    } 

    //final menu object 
    return menu; 
})(); 

window.menu = menu; 
})(window,jQuery); 

ときに私のページがロードされ、コードが呼び出されます。

menu.init(); 

それは順番に警告を与える:私が期待したよう

initialising tab 
initialising curtain 
initialising content 

。私はこのようになり、コンテンツのコンポーネントを変更した場合でも:

//menu content component 
    var content = (function(){ 

     //public properties 
     var content = { 
      init:doStuff 
     } 

     //private properties 
     function doStuff(){ 
      alert("initialising Content") 
     } 

     //CHECK ACCESS TO PREVIOUS VARIABLES 
     curtain.init(); 

     //return public properties 
     return content; 
    })(); 

それは順番にアラートを提供します:

initialising curtain 
initialising tab 
initialising curtain 
initialising content 

だから私はそれはwasnにもかかわらず、カーテン変数にアクセスすることが可能であることがわかり引数としてモジュールに渡されませんでした。 私は各モジュールが自己完結型だと思っていましたが、私はこれが当てはまらないことを発見しました。特に私の例に役立つだろう、 ありがとうダン。

答えて

2

各モジュールは自己完結型ではなく、作成されたモジュールのスーパーセットである新しいスコープを作成します。 Javascriptで新しいスコープを定義するのは、functionステートメントだけです。新しいスコープ内では、同じ名前の変数で上書きされない限り、外側スコープからのすべてが表示されます。内側のスコープ内のものは、その外側のものには何も表示されません。

var global; 
function outer() { 
    var outerVar; 

    function inner() { 
     var innerVar; 

     // global, outerVar, and innerVar are visible 

    } 
    function inner2() { 
     var inner2var, outerVar; 

     // global and inner2var are visible 
     // outerVar hides the previous outerVar, which is no longer accessible 

    } 

    // global and outerVar (the first one) are visible 

} 

あなたの機能が自己実行しているという事実は違いにはなりません。外側のスコープで作成されたものは、内側のスコープ内に表示されます。ただし、同じ名前の新しいローカル変数を作成する場合を除きます。

内側の範囲については、外側に作成されたものはすべてグローバルと同じです。 (そして、グローバルはデフォルトのスコープで作成された変数で、ブラウザの "ウィンドウ"です)。

内側の範囲は、一方向のガラスの後ろにあるように考えることができます。あなたはまだ世界のすべてを見ることができますが、世界はあなたを見ることができません。そして、あなたはもはや見ることができないように、常に一方向ガラスをブロックすることを選択することができます。しかし、何も見ることはできません。

+0

これはまだES6がリリースされた現在のものですか? –

+0

はい、ES6はES5のスーパーセットです。 'let'のような新しいスコープ構造がいくつかありますが、このコードはまだ有効です –

0

現在のスコープは、スコープに含まれるスコープを見ることができます。したがって、コンテンツはまだカーテンを含むメニュー内の変数にアクセスできます。

0

これは、各オブジェクトで 'return'を呼び出すと、各コンポーネントの内部 'publicプロパティ'オブジェクトである戻り値をコンポーネント変数に割り当てているためです。

var tab = (function(){ 

    //public properties 
    var tab = { 
     init:doStuff 
    } 

    //private properties 
    function doStuff(){ 
     alert("initialising Tab") 
    } 

    //return public properties 
    return tab; 
})(); 

元の変数 'tab'には、実行中の匿名関数の結果が割り当てられます。この場合のオブジェクトは、関数の実行終了時にこのオブジェクトを返すため、

var tab = { 
     init:doStuff 
    } 

です。

あなたが行っていることを達成するには、関数のスコープ内の変数にアクセスする「public」修飾子関数を持つオブジェクトを返します。関数内に作成された変数は、その関数またはそのスコープ内の関数にのみスコープを持ち、それによってそれらを効果的に非公開にします(JavaScriptは機能スコープです)。次の例では、コードのお手伝いをする必要があります。

var tab = (function(){ 

    //public properties 
    var PublicProperties = { 
     init:doStuff, 
     modifyPrivateVar: function(value){ 
      this.somePrivateVariable = value; 
     } 
    } 

    //private variables/properties 
    var doStuff = function(){ 
     alert("initialising Tab") 
    } 

    var somePrivateVariable = 'private!'; 

    //return public properties 
    return PublicProperties; 
})(); 

今すぐあなたの変数「タブ」の値が割り当てられます匿名関数の実行によって(PublicPropertiesオブジェクト)それに戻りました。関数 "init"と "modifyPrivateVar"にアクセスできますが、 "doStuff"を呼び出すことも、somePrivateVariableを直接変更することもできません。これは、修飾子関数を介して変数を変更できますが、直接アクセスすることはできないため、それを効果的に非公開にすることができます。

"init"関数をコンストラクタとして呼び出す場合は、コンポーネントの匿名関数の実行の実行中に "コンストラクタ関数"を実行するか、コードをインラインで記述して実行する必要がありますコンポーネントの匿名関数が実行されると...そうでなければ、privateであればinit関数に関連するものを返すべきではなく、安全な方法でオブジェクトを変更/アクティブ化するために使用できる関数のみを返します。