2012-04-25 54 views
0

我學習JavaScript和模塊模式,但我在我的代碼犯了一個錯誤,它不對證明一些我雖然是真實的關於這個模式的概念。我的基本代碼是這樣的:的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 

因此,我認爲,這是能夠訪問,即使它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的發佈嗎? – 2016-06-17 13:50:10

+0

是的,ES6是ES5的超集。有一些新的作用域結構像'let',但是這個代碼仍然有效 – 2016-06-17 14:31:17

0

任何函數的當前作用域都可以看到它包含的作用域。所以,內容仍然可以訪問菜單中的任何變量,其中包括窗簾。

0

這是發生,因爲當你調用中的每個對象「迴歸」,你要分配到組件變量的返回值,這是內在的「公共屬性」的對象中每個組件。

var tab = (function(){ 

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

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

    //return public properties 
    return 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」函數作爲構造函數調用,則必須在執行組件的匿名函數執行過程中執行「構造函數」,或者只是將代碼在線編寫並執行因爲組件的匿名函數會執行....否則,如果它是私有的,則不應該返回與init函數相關的任何內容,只返回可用於以安全方式修改/激活對象的函數。