2013-03-22 75 views
4

我正在尋找使用對象創建命名空間和自我執行匿名函數。哪一個被認爲是更好的選擇?jQuery命名空間使用對象和自我執行匿名函數

使用對象,給出一個唯一的名稱'myAppName'足以防止碰撞?

var myAppName = { 
    val1: "abc", 
    val2: "xyz", 
    myFunc1: function() { 
     return this.val2; 
    } 
} 

console.log(myAppName.val1); // abc 
console.log(myAppName.myFunc1()); // xyz 

使用自執行的匿名函數:

(function() { 
val1 = "abc"; 
    var val2 = "xyz"; 

    myFunc1 = function() { 
     return val1; 
    } 

    var myFunc2 = function() { 
     return val2; 
    } 
})(); 

console.log(val1); // abc 
console.log(myFunc1()); // abc 
console.log(myFunc2()); // xyz 

在自執行功能上面的代碼,它們似乎都執行。在變量和函數名之前是否有使用和不使用var的含義?我不太明白。有沒有辦法將變量和函數設置爲私有和公共的?或者是自執行功能中的所有內容都是私有的?

如果我在自我執行功能之前使用'var'會發生什麼?

var myAppName = (function() { 
val1 = "abc"; 
    var val2 = "xyz"; 

    myFunc1 = function() { 
     return val1; 
    } 

    var myFunc2 = function() { 
     return val2; 
    } 
})(); 
+1

在你的第二個代碼塊中,調用'console.log(myFunc2());'不會顯示'xyx'。相反,它會拋出'ReferenceError:myFunc2未定義'。這是因爲'myFunc2'對匿名函數是本地的。 – 2013-03-23 04:04:02

+1

在你的第三個代碼塊中,'myAppName'將會是'undefined',因爲你沒有從函數返回任何東西。 – 2013-03-23 04:05:11

回答

4

我的第一個答案試圖解決您的原始問題,並展示如何設置一個名稱空間。我決定添加第二個答案來解決評論中提出的問題,以回答我的第一個問題。

全局變量實際上是window對象的屬性。如果在函數外部使用var,則正在定義全局變量。如果在函數內部使用var,那麼您正在定義一個局部變量。如果參考變量someValue而不用var進行聲明,則與參考window.someValue相同。

以下代碼顯示了設置全局變量的不同方式,以及定義局部變量的一種方法。

window.global1 = 'abc'; 
global2 = 'def'; 
var global3 = "ghi"; 

(function() { 
    window.global4 = 'jkl'; 
    global5 = 'mno'; 
    var local1 = 'xyz'; 
})(); 

console.log(global1); // 'abc' 
console.log(global2); // 'def' 
console.log(global3); // 'ghi' 
console.log(global4); // 'jkl' 
console.log(global5); // 'mno' 
console.log(local1); // ReferenceError: local1 is not defined 

一般來說,您想限制設置全局變量(至少在創建JavaScript庫時)。命名空間基本上只是一個全局變量。當你將所有其他東西放在該名稱空間下時,只添加了一個全局變量。

我認爲這也是避免設置上述global2global5等全局變量的最佳做法。相反,您應該使用函數的var oustide(如global3)或在window對象上設置屬性(如global1global4)。

從我的其他答案借用的代碼示例中,我們可以創建這樣一個命名空間:

var myApp = (function() { 
    var privateValue = 'abc'; // Don't forget "var" here. 

    function privateFunction() { 
     return privateValue; 
    } 

    return { 
     publicValue: 'xyz', 

     publicFunction: function() { 
      return privateFunction(); 
     } 
    } 
})(); 

我們可以通過執行以下操作可以達到同樣的,但我認爲這是不好的風格:

(function() { 
    var privateValue = 'abc'; // Don't forget "var" here. 

    function privateFunction() { 
     return privateValue; 
    } 

    myApp = { 
     publicValue: 'xyz', 

     publicFunction: function() { 
      return privateFunction(); 
     } 
    } 
})(); 

在這兩種情況下,我們都設置了myApp全局變量,但我認爲前者要比後者明顯得多。

只是要清楚,在這兩種情況下,我們將解決公共變量作爲myApp.publicValue和呼叫使用myApp.publicFunction()公共功能和匿名函數之外,我們將無法引用privateValueprivateFunction

3

將所有的代碼放在一個命名空間下,肯定會有助於避免名稱衝突。如果確實有碰撞,更改代碼以處理它會容易得多。

如果一切都需要公開,您的第一個代碼示例沒有問題。如果你想要一些東西是私有的,使用匿名,立即執行的功能,如:

var myApp = (function() { 
    var privateValue = 'abc'; // Don't forget "var" here. 

    function privateFunction() { 
     return privateValue; 
    } 

    return { 
     publicValue: 'xyz', 

     publicFunction: function() { 
      return privateFunction(); 
     } 
    } 
})(); 

通知匿名函數如何返回包含公共變量和函數的對象。如果你沒有在「privateValue」之前加上「var」,那麼你沒有定義一個局部變量; (這是真正的「窗口」對象的屬性),取而代之的是,你引用一個全局變量

如果您正在使用jQuery,我提出以下建議:

(function(window, $, undefined) { 

    var myApp = (function() { 
     var privateValue = 'abc'; // Don't forget "var" here. 

     function privateFunction() { 
      return privateValue; 
     } 

     return { 
      publicValue: 'xyz', 

      publicFunction: function() { 
       return privateFunction(); 
      } 
     } 
    })(); 

    // Put myApp in the global scope. 
    window.myApp = myApp; 

})(window, jQuery); 

這樣一來,你是安全的使用$()而不是jQuery()。您也可以安全地將undefined視爲一個常數。您還可以更輕鬆地處理某人已經覆蓋窗口對象的情況。

+0

謝謝。在執行'(function(){'和'var myApp =(function(){'?)之間有區別嗎?或者它是同樣的事情?我想在前者中,我訪問變量或函數:'console。 log(val1);'和後者是這樣的:'console.log(myApp.val1);'。是嗎?除此之外的任何其他差異? – user1448031 2013-03-22 23:45:16

+0

@ user1448031 - 我添加了另一個答案,希望能回答你的問題。 – 2013-03-23 04:07:55

相關問題