1

私はjavascriptとモジュールパターンを学んでいますが、コードを間違えたため、このパターンについては正しいとはいえ、いくつかの概念が間違っていることがわかりました。私の基本的なコードは次のようなものです。

(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

したがって、引数としてモジュールに渡されなくても、カーテン変数にアクセスできることがわかります。各モジュールは自己完結型だと思いましたが、そうではないことを発見しました。とにかく、モジュールが必要な変数にのみアクセスできるようにすることはできますか?特に私の例には役立つでしょう、ありがとうダン。

4

3 に答える 3

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

} 

関数が自己実行しているという事実は違いを生みません。外側のスコープで作成されたものはすべて、それよりも優先される同じ名前の新しいローカル変数を作成しない限り、内側のスコープに表示されます。

内部スコープに関する限り、内部スコープの外部で作成されたものはすべて、グローバルスコープとほとんど同じです。(グローバルは、デフォルトのスコープであるブラウザの「ウィンドウ」で作成された変数です)。

内側のスコープは、マジックミラーの後ろにあるようなものと考えることができます。あなたはまだ世界のすべてを見ることができますが、世界はあなたを見ることができません。また、いつでもマジックミラーをブロックして、外が見えないようにすることができます。しかし、何も見ることができなくなります。

于 2012-04-25T21:23:18.107 に答える
0

関数の現在のスコープは、含まれているスコープを確認できます。そのため、コンテンツは、カーテンを含むメニュー内のすべての変数に引き続きアクセスできます。

于 2012-04-25T21:25:40.190 に答える
0

これは、各オブジェクトで「return」を呼び出すときに、各コンポーネントの内部の「publicproperties」オブジェクトである戻り値をコンポーネント変数に割り当てているために発生します。

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;
})();

これで、変数'tab'に、無名関数の実行によって返された値(PublicPropertiesオブジェクト)が割り当てられます。関数「init」および「modifyPrivateVar」にアクセスできますが、「doStuff」を呼び出したり、「somePrivateVariable」を直接変更したりすることはできません。これは、修飾子関数を使用して変数を変更できるが、直接アクセスできないため、事実上プライベートにすることができることを示しています。

「init」関数をコンストラクターとして呼び出す場合は、コンポーネントの無名関数実行の実行内で「コンストラクター関数」を実行するか、コードをインラインで記述するだけで、コンポーネントの無名関数として実行されます。関数が実行されます....それ以外の場合は、init関数に関連するものを返す必要はありません。プライベートの場合は、オブジェクトを安全な方法で変更/アクティブ化するために使用できる関数のみを返します。

于 2012-04-25T21:45:03.267 に答える